2

这是Java 双重检查锁定的后续。

下面的代码片段有 2 个有趣的特征。

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 吗?

谢谢,丰富

4

2 回答 2

2

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

顺便说一句,您真的不需要学习所有允许重新排序的规则:这只是 JIT 编译器实现者的必读内容。

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

于 2013-08-02T17:58:10.327 回答
1

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

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

现在它没有重新排序的原因。监视器进入后无法重新订购普通商店。

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

第一个操作:MonitorEnter

第二次操作:NormalStore

是否可以重新订购:否

于 2013-08-02T17:57:41.253 回答