[英]Can I avoid the volatile read in double checked locking once initialized like this?
By using a volatile boolean that is read only if the instance is null, can I avoid the default/frequent volatile read once the instance is initailized like so? 通过使用仅当实例为null时才可读的volatile布尔值,是否可以避免实例实例化后的默认/频繁volatile读取? Havent seen anyone recommend double checked locking like this, but seems to avoid volatile reads once fully initialized...
Havent看到有人建议像这样进行双重检查锁定,但似乎避免了在完全初始化后进行易失性读取...
public class Singleton {
private static volatile boolean initialized = false;
private static Object lock = new Object();
private static Singleton instance;
public static Singleton getInstance(){
if(instance != null) return instance;
if(!initialized){
synchronized(lock){
if(!initialized){
instance = new Singleton();
initialized = true;
}
}
}
return instance;
}
} }
No, you cannot. 你不能。 If thread A has reached the synchronized block and is executing the
如果线程A已到达同步块并正在执行
instance = new Singleton();
line, a thread B entering your function could see instance
as initialized before thread A has finished constructing the object. 在线程A结束构造对象之前,进入函数的线程B可能会看到
instance
已初始化。 So you risk having thread B try to work on a partially constructed object. 因此,您冒着使线程B尝试在部分构造的对象上工作的风险。
See the DLCP article for variations and explanations on this pattern. 有关此模式的变体和说明,请参见DLCP文章。
Your optimization attempt is not only premature, but also fruitless, quoting Are volatile variable 'reads' as fast as normal reads? 您的优化尝试不仅过早,而且徒劳无功,引用volatile变量“读取”的速度是否与普通读取一样快? :
:
On an x86, there is no additional overhead associated with volatile reads.
在x86上, 没有与易失性读取相关的额外开销 。
If you want lazy instantiation but concerned about performance, use "inner class" approach - it is cleaner and shorter (and a tiny bit more efficient as well). 如果您想要延迟实例化但又担心性能,请使用“内部类”方法-它更简洁,更短(并且效率更高一点)。 Something like that:
像这样:
public class Singleton {
private static class SingletonHolder {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
The trick is that instance is created during initialization of the inner class - that will happen when class is first referenced, which is first call to getInstance()
. 诀窍是,实例是在内部类的初始化期间创建的-首次引用类时会发生这种情况,这是对
getInstance()
首次调用。 BTW - avoid such "static" singletons, unless there are truly good reasons to use them. 顺便说一句-除非有充分的理由使用它们,否则请避免使用此类“静态”单身人士。
volatile read is (almost) free on most hardware, volatile write is expensive, though... So why bother? 易失性读取在大多数硬件上(几乎)是免费的,但是易失性写入非常昂贵,但是...为什么要打扰?
The short answer is no. 最简洁的答案是不。 between
instance = new Singleton()
and initialized = true
on a weak memory model where stores can be reordered a reader might see an uninitialized Signleton. 在可以重新排序存储的弱内存模型上,在
instance = new Singleton()
与initialized = true
,读者可以看到未初始化的Signleton。 on x86 and sparc TSO no store-store reorder but on ARM and IA64 it does happen. 在x86和sparc TSO上,没有存储重新排序,但是在ARM和IA64上确实发生了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.