Java双重检查锁定解决方案?

时间:2013-08-02 17:52:19

标签: java synchronization singleton double-checked-locking

这是Java double checked locking的后续内容。

以下代码段有两个有趣的特征。

1)在对象准备好使用之前,需要调用单独的init()方法。所以volatile不起作用(我知道,为什么我不把init()中的代码放到构造函数中?这是为了说明的目的)。

2)它使用tmp变量进行初始化,并在初始化完成后分配给实例。

if (instance == null) {
synchronized (mutex) {
    if (instance == null) {
        AClass tmpInstance = new AClass();
        tmpInstance.init();
        instance = tmpInstance;
    }
}
}

那么,这是否受到重新排序问题的影响,即可以在调用tmpInstance.init()之前将实例分配给tmpInstance?

谢谢, 富

2 个答案:

答案 0 :(得分:2)

重要的是,在完成所有初始化之后,您将instance指定为最后一个操作。由于instance(希望)是易变的,这将确保所有初始化对后来的读者都可见。

顺便说一句,你真的没有必要学习允许重新排序的所有规则:这只是JIT编译器实现者的强制读取。

作为Java程序员,您需要牢记的是Java内存模型为您提供的两个简单保证(一个约为synchronized,另一个约为volatile)。 JMM重写的全部内容(从JLS 3开始)是允许我们针对一个非常简单的并发模型进行编程。

答案 1 :(得分:1)

  

那么,这是否受到重新排序问题的影响,即可能是   在调用tmpInstance.init()之前分配给tmpInstance?

否,但它受到volatile确实解决的可见性问题的影响。所以你仍然应该声明instance volatile。

现在它不受重新排序的原因。监视器进入后,正常存储无法重新排序。

http://g.oswego.edu/dl/jmm/cookbook.html

  

第一次操作:MonitorEnter

     

第二次操作:NormalStore

     

可以重新排序:否