我也看到过类似的问题,但我仍然有些困惑。寒冷在这里:
private volatile static DoubleCheckSingleton instance;
private DoubleCheckSingleton() {}
public static DoubleCheckSingleton getInstance(){
if(instance==null){ //first
synchronized (DoubleCheckSingleton.class){
if(instance==null){ // second
instance=new DoubleCheckSingleton();
}
}
}
return instance;
}
在此问题Why is volatile used in double checked locking中,它说,没有volatile关键字,线程可能在构造函数完成之前分配实例变量,因此另一个线程可能会看到一半构造的对象,这可能会导致严重的问题。
但是我不知道波动如何解决问题。易失性用于确保可见性,因此,当线程A将半结构化对象分配给实例变量时,另一个线程可以立即看到更改,这使情况变得更糟。
挥发物如何解决问题,请有人向我解释。谢谢!
线程可以在构造函数完成之前分配实例变量
实际并非如此。在代码示例中,赋值就在那里:
instance=new DoubleCheckSingleton()
显然,执行该分配的线程可能无法在返回构造函数调用之前进行分配。
问题是,当两个不同的线程在两个不同的处理器上运行而没有任何同步时,它们不一定会同意分配发生的顺序。因此,即使线程A分配了新对象的字段(在new DoubleCheckSingleton()
调用之内)之前,它也分配了instance
,线程B仍可能会无序看到这些分配。线程B在看到instance
所做的其他一些事情之前,可能已经看到new DobuleCheckSingleton()
的分配。
将instance
声明为volatile
会同步线程。 volatile
保证everything线程A所做的之前当线程B获取volatile
变量的值时,线程B会为它分配一个volatile
变量。