Iva*_*nko 4 java multithreading
据我所知,这是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;
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否缺少volatile是一个严重的错误或只是一个轻微的不完美与可能的性能缺陷假设_barInstance只通过访问getBar.
我的想法如下:synchronized介绍发生在之前的关系.初始化的线程_barInstance将其值写入主存储器,离开同步块.因此,_barInstance即使不是,也不会进行双重初始化volatile:其他线程null在其本地副本中有_barInstance(true在第一次检查中获取),但在进入同步后必须在第二次检查中从主存储器中读取新值阻止(获取false并不重新初始化).所以唯一的问题是每个线程的锁定获取过多.
据我所知,它在CLR中是正确的,我相信它在JVM中也是正确的.我对吗?
谢谢.
小智 7
在以下情况下,不使用volatile可能会导致错误:
getBar()并发现_barInstance是nullBar对象并更新对象的引用_barInstance.由于某些编译器优化,这些操作可能不按顺序进行.getBar()并看到非空,_barInstance但可能会在_barInstance对象的成员字段中看到默认值.它基本上看到了部分构造的对象,但引用不是null.的volatile改性剂将禁止写入或读取可变的_barInstance相对于任何先前的读或写.因此,它将确保线程2不会看到部分构造的对象.
有关详细信息,请访问:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html