我正在阅读Nir Shavit的“多处理器计算的艺术”。它解释了Java Memory Model并在第62页给出了一个例子:
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
并说:
此模式一旦出现,就是不正确的。在第5行,构造函数 调用似乎在分配实例字段之前发生,但是 Java内存模型允许这些步骤不按顺序发生, 有效地使部分初始化的Singleton对象可见 其他节目。
那么,这是否意味着这种同步可能无法保证我们对Singleton的要求?
答案 0 :(得分:1)
那么,这是否意味着这种同步可能无法保证 我们想从Singleton那里得到什么?
这取决于你想要的单身人士。如果您只想要一个实例,则代码段中的解决方案将实现该目标。如果你只想要一个实例,并且你想要在访问它时完美地初始化该实例(那要求太多了吗?),那么,不,你将无法通过代码片实现这一点。
另一个线程调用getInstance
并读取instance
字段的值
if (instance == null) {
可能会看到一个指定值,该值引用了尚未由控制器初始化的对象。由于该值不是null
,因此该方法返回它并且未初始化的对象泄漏。
通过将字段标记为volatile
来修复此问题。