美文网首页
单例模式-双重检查加锁为什么需要加上volatile关键字?

单例模式-双重检查加锁为什么需要加上volatile关键字?

作者: qiaoflin | 来源:发表于2020-11-24 10:33 被阅读0次
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

相关文章

网友评论

      本文标题:单例模式-双重检查加锁为什么需要加上volatile关键字?

      本文链接:https://www.haomeiwen.com/subject/wociiktx.html