单例模式 双重检测机制答疑
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
mem = allocate(); 1 //Allocate memory for Singleton object.
singleton = mem; 2 //Note that instance is now non-null, but
//has not been initialized.
ctorSingleton(singleton ); 3 //Invoke constructor for Singleton passing
//instance.
在 JVM 的即时编译器中存在指令重排序的优化.也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2.如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。
疑问: 为什么使用了synchronized同步还会被其他线程抢占?