public class DoubleCheckedLocking {
private static DoubleCheckedLocking instance;
public static DoubleCheckedLocking getInstance(){
if(instance == null){// 4.第一次检查
synchronized (DoubleCheckedLocking.class){ // 5.加锁
if(instance == null){ // 6. 第二次检查
instance = new DoubleCheckedLocking(); // 7.问题的根源处在这里
}
}
}
return instance;
}
}
上面代码有一个问题:
在线程执行到第4行,代码读取到 instance 不为 null 时,instance引用的对象有可能还没有完全初始化。
问题的根源:
前面的 双重检查锁定上述代码的第7行(instance = new DoubleCheckedLocking())创建了一个对象。这一行代码可以分解为 下面的3行代码。
memory = alloct(); //:1:分配对象的内存空间
ctorinstance(memory); //2: 初始化对象
instace = memory; //3:设置instace指向刚分配的内存地址
上面的3行伪代码中的2和3之间,可能被重排序,重排序如下:
memory = alloct(); //:1:分配对象的内存空间
instace = memory; //3:设置instace指向刚分配的内存地址
// 主要此对象还没有被初始化
ctorinstance(memory); //2: 初始化对象
多线程执行结果如下:
解决方案: 加上volatile关键字
public class DoubleCheckedLocking {
private static volatile DoubleCheckedLocking instance;
public static DoubleCheckedLocking getInstance(){
if(instance == null){// 4.第一次检查
synchronized (DoubleCheckedLocking.class){ // 5.加锁
if(instance == null){ // 6. 第二次检查
instance = new DoubleCheckedLocking(); // 7.问题的根源处在这里
}
}
}
return instance;
}
参考链接:https://fd2020.blog.csdn.net/article/details/108359755#comments_13360953