很多人说因为内存什么的原因,双重检查锁可能会失效,小白实在看不太懂,
只想知道结论是什么?双重检查锁到底该不该用?
如果不该用,那单例模式更好的写法是什么?
附代码
class SingleTon2 {
private static SingleTon2 s2 = null;
public static SingleTon2 getInstance() {
if (s2 == null) {
synchronized (SingleTon2.class) {
if (s2 == null) {
s2 = new SingleTon2();
}
}
}
return s2;
}
private SingleTon2() {
System.out.println("懒汉式初始化.......");
}
}
双重检查锁在多线程并发时,可能会因为JVM指令重排出问题
代码中 s2 = new SingleTon2();在JVM中可能会分解为:
memory = allocate(); //1:分配对象的内存空间
initInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址
如果因为某些原因导致指令重排,指令的执行顺序可能为:
memory = allocate(); //1:分配对象的内存空间
instance = memory; //3:设置instance指向刚分配的内存地址,此时对象还没被初始化
initInstance(memory); //2:初始化对象
此时,如果在instance=memory执行,但未完成对象初始化时,另一个线程执行第一个if(s2==null)会返回false直接返回未初始化的
Singleton实例,导致错误。