在Java中使用volatile在单例双null检查实现中 [英] Use of volatile in singleton double null check implementation in java
问题描述
我想知道在Singleton的双null检查实现中将Instance变量设置为volatile的用途.因为按照我的理解,同步块提供先于隐式发生.没有两个线程可以同时访问该同步块,并且在从同步块退出时,线程将其所有本地缓存的数据写入主内存. 我进行了很多搜索,但仍然对这种实现方式有疑问.请说明正确用法.
I want to know what is use of making Instance variable as volatile in double null check implementation of Singleton. Because as per my understanding synchronize block provide happens before implicitly. No two threads can access that synchronized block concurrently and while exiting from synchronized block, thread write all its local cached data to main memory. I search a lot but still i have doubts in this implementation. Please explain correct use.
private volatile Singleton INSTANCE;
public Singleton get() {
if (INSTANCE == null) {
synchronized (this) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
在上面的双重检查代码中.如果我不使实例具有可变性,可能会出现什么问题?因为当第一个线程进入同步块时,其他线程将无法访问该块.当第一个线程离开该块时.对象将被创建,并且由于发生在属性之前,实例的最新值将被写入主存储器.那么为什么在这种情况下挥发物很重要?
In above double checking code. What may b the issue if i dont make my instance as volatile. Because when first thread enter in synchronize block, no other thread will get access to that block. And when first thread leaves that block. Object will be created and due to happens before property, latest value of instance will be written in main memory. So why volatile is important in this scenario?
Here's a link (Is there any need to add volatile keyword to guarantee thread-safe singleton class in java?) of similar question. But answers are not very clear. I don't think in above given scenario any kind of JVM optimization can cause breaking of happens before of synchronize block
推荐答案
volatile
在这里很重要,因为JVM在字节码级别上是内部的.声明
volatile
is important here because of the internals of the JVM on the bytecode level. The statement
INSTANCE = new Singleton()
在字节码级别实际上是这样的:
is on bytecode level actually something like that:
1. INSTANCE = create Singleton object
2. call constructor of INSTANCE
如果INSTANCE为volatile
,则JVM保证从其他线程的角度来看,将1 + 2作为原子操作执行.通过将实例存储在堆栈上,然后再将其存储在字段中.如果不是 volatile
,则可能是其他线程可以在调用构造函数之前已经看到对Singleton的引用.因此,这些线程可能会看到不完整的对象.
if INSTANCE is volatile
the JVM guarantees you that 1+2 are executed as an atomic operation from the point of view of other threads, e.g. by storing the instance on the stack before storing it in the field. If it is not volatile
it might be that other threads can already see the reference to Singleton before the constructor has been called. Thus these threads might see an incomplete object.
这篇关于在Java中使用volatile在单例双null检查实现中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!