首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用前的Java锁变量赋值。为什么?

使用前的Java锁变量赋值。为什么?
EN

Stack Overflow用户
提问于 2011-11-05 11:18:03
回答 5查看 1.4K关注 0票数 7

在很多Java源代码中,(例如LinkedBlockingDeque),我看到了这样的东西;

代码语言:javascript
复制
final ReentrantLock lock = new ReentrantLock();

public void putLast(E e) throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
       // do stuff
    } finally {
        lock.unlock();
    }
}

我理解基本模式(锁,最终解锁),但我的问题是,为什么在使用它之前对本地作用域的锁变量进行赋值?,为什么要这样做,而不是下面的?

代码语言:javascript
复制
final ReentrantLock lock = new ReentrantLock();

public void putLast(E e) throws InterruptedException {
    this.lock.lock();
    try {
       // do stuff
    } finally {
        lock.unlock();
    }
}

它会影响优化吗?第一个例子能防止锁粗化吗?

评论后的编辑:如果你真的不知道为什么会这样,请不要添加答案。这是来自Java源代码,@author标记是Doug,所以我很确定它存在是有原因的。请不要指出代码是完全等价的。

谢谢

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-11-05 12:33:08

当您在方法中分配给局部变量时,编译器可以进行一些优化。请参阅在ArrayBlockingQueue中,为什么要将最终成员字段复制到局部变量中?

票数 7
EN

Stack Overflow用户

发布于 2011-11-05 11:30:28

在这段代码中,这并不重要:这两个示例的工作原理完全相同。但是,如果实例变量锁不是最终锁,那么它可能会产生影响,因为实例变量可能在锁定操作期间被更改:然后您希望确保您解锁的锁与您最初锁定的锁相同。

但是,由于锁是最终的,这并不重要:在您的第一个例子中的局部变量分配是多余的。

票数 2
EN

Stack Overflow用户

发布于 2011-11-05 12:49:15

在代码中,我发现了同一作者Doug的两种方法的示例:

  • LinkedBlockingDeque (自JDK1.6以来)使用“直接访问”方法。
  • CopyOnWriteArrayList (因为JDK1.5)使用“局部变量”方法。

java.util.concurrent中的每个成语都有更多的例子,但似乎每个类都选择了一致的风格。

请注意,在所有相关情况下,lock字段已被声明为final。这是最重要的部分,因为最终字段的内存模型语义在JVM (见JLS)中有点特殊。

在此基础上:是否使用本地副本并不会影响多线程正确性。

还请注意,code在更新的代码中选择了较短的样式(如示例所示)。因此,“获取本地副本”成语可能是java.util.concurrent成为JDK的一部分之前以及JVM内存模型被适当采用之前遗留下来的一些东西。我推测,在采用之前的代码可能如下所示:

代码语言:javascript
复制
public void op(){
    ReentrantLock lock = getLock();
    lock.lock();
    try {
        realOp();
    } finally {
        lock.unlock();
    }
}

其中getLock()确实包含了一些粗糙的多线程安全逻辑。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8019831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档