加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java中双重检查锁定中的volatile

发布时间:2020-12-15 04:25:00 所属栏目:Java 来源:网络整理
导读:参见英文答案 Why is volatile used in double checked locking????????????????????????????????????6个 据我所知,这是Java中双重检查锁定模式的正确实现(自Java 5起): class Foo { private volatile Bar _barInstance; public Bar getBar() { if (_barIns
参见英文答案 > Why is volatile used in double checked locking????????????????????????????????????6个
据我所知,这是Java中双重检查锁定模式的正确实现(自Java 5起):

class Foo {
    private volatile Bar _barInstance;
    public Bar getBar() {
        if (_barInstance == null) {
            synchronized(this) { // or synchronized(someLock)
                if (_barInstance == null) {
                    Bar newInstance = new Bar();
                    // possible additional initialization
                    _barInstance = newInstance;
                }
            }
        }
        return _barInstance;
    }
}

假设只有通过getBar访问_barInstance,我想知道是否缺少volatile是一个严重的错误,或者只是一个可能的性能缺陷的轻微缺陷.

我的想法如下:synchronized介绍发生之前的关系.初始化_barInstance的线程将其值写入主内存,而不是同步块.因此,即使它不是volatile,也不会有_barInstance的双重初始化:其他线程在_barInstance的本地副本中为空(在第一次检查中为true),但必须在第二次检查中从主内存读取新值进入synchronized块后检查(获取false并不重新初始化).所以唯一的问题是每个线程的锁定获取过多.

据我所知,它在CLR中是正确的,我相信它在JVM中也是正确的.我对吗?

谢谢.

解决方法

在以下情况下,不使用volatile可能会导致错误:

>线程1进入getBar()并发现_barInstance为null
>线程1尝试创建Bar对象并更新对_barInstance的引用.由于某些编译器优化,这些操作可能不按顺序进行.
>同时,线程2进入getBar()并看到非null _barInstance但可能会在_barInstance对象的成员字段中看到默认值.它基本上看到了部分构造的对象,但引用不是null.

volatile修饰符将禁止相对于任何先前的读或写写入或读取变量_barInstance.因此,它将确保线程2不会看到部分构造的对象.

有关详细信息:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读