prestonewang 2011-07-19 02:27
浏览 231
已采纳

JDK1.5内存模型下的DCL问题

问题:请看下面的代码,有个两个线程,线程A和线程B,时间上线程A先于线程B执行,线程A刚执行完synchronized代码块(语句7),在构造实例时是乱序执行的,如:第1步,在堆中分配空间;第2步,返回引用给instance变量;第3步,调用LazySingleton的构造函数进行初始化。在JDK1.5的内存模型下,线程A刚执行完synchronized代码块(语句7),线程B开始执行语句2,这时线程B得到的instance,会不会还未完成初始化完。如果不会的话,是volatile保证了构造实例过程的正确顺序,还是synchronized代码块中构造实例的过程压根就不能乱序执行?并请帮忙指出在Java Language Specification的出处。如果会的话,那就说下面的DCL解决方法在JDK1.5的内存模型下依然有问题。

[code="java"]
public class LazySingleton {

private int xxx;

private volatile static LazySingleton instance;

private LazySingleton() {
    this.xxx = 100;                                       // (1)
}

public static LazySingleton getInstance() {
    if (instance == null) {                               // (2)
        synchronized(LazySingleton.class) {               // (3)
            if (instance == null) {                       // (4)
                instance = new LazySingleton();           // (5)
            }                                             // (6)
        }                                                 // (7)
    }                                                     // (8)
    return instance;                                      // (9)
}

public int getXxx() {
    return xxx;                                           // (10)
}

}

[/code]

  • 写回答

10条回答 默认 最新

  • kolor_cn 2011-07-19 21:08
    关注

    [quote]OK,我看错了。这个实现有点怪。getInstance是static的,但实现方法用的却是lazy load。锁住.class是正确的,相当于.class是一个共享标志变量而已,保证里面的代码不被并发。但volatile是多余的,static数据是所有线程共享的[/quote]

    兄弟,这里的volatile可是关键,可不是多余的,少了volatile,这个DCL就是有问题的,happens-before原则里有“(3)对volatile字段的写入操作happens-before于每一个后续的同一个字段的读操作。 ”这么一条,关键所在

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(9条)

报告相同问题?

悬赏问题

  • ¥15 把Excel导入MATLAB显示错误怎么解决?
  • ¥15 Java中消息和缓存如何使用
  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx