我读了同步新实例创建的原因是两个线程可以同时访问getInstance并发现_instance为null并创建了Singleton类的两个实例。所以为了消除我们同步它。但是,为什么再次引入双重检查的锁定方法,检查同步块内的实例是否为空。这有必要吗?一旦代码块被同步,它已经线程安全了吗?
public class Singleton {
private static Singleton _instance = null;
private Singleton() { }
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
_instance = new Singleton(); // why need to again check null
}
}
return _instance;
}
}
答案 0 :(得分:0)
synchronized
块将按顺序执行(即一次一个线程),但这还不够,因为对_instance = new Singleton()
的第二次调用可能会覆盖第一次。
如果在第一个线程评估_instance == null
表达式后立即发生一个上下文切换,并且在另一个线程评估_instance == null
表达式之前不会发生其他上下文切换,那么这是一个合理的场景。
因此,一旦进入synchronized
块,当前线程必须确保_instance
仍为null
,然后再将其设置为new Singleton()
。