<分区>
据我所知,这是 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;
}
}
我想知道如果 _barInstance
仅通过 getBar
访问,那么缺少 volatile
是否是一个严重的错误或只是一个可能存在性能缺陷的轻微缺陷。
我的想法如下:synchronized
引入了happens-before 关系。初始化 _barInstance
的线程将其值写入主内存,离开同步块(synchronized block)。因此,即使 _barInstance
不是 volatile
,也不会对其进行双重初始化:其他线程在其 的本地副本中具有
(第一次检查得到null
_barInstancetrue
),进入synchronized block 后第二次检查必须从主存中读取新值(get false
并且不进行重新初始化)。因此,唯一的问题是过度获取每个线程一个锁。
据我所知,它在 CLR 中是正确的,我相信它在 JVM 中也是正确的。我说得对吗?
谢谢。