DCL 单例模式设计为什么需要 volatile 修饰实例对象

DCL 问题,是在基于双重检查锁设计下的单例模式中,存在不 完整对象的问题。而这个不完整对象的本质,是因为指令重排序导致的。

java 复制代码
public class DCLExample {
    private static DCLExample instance;
    public static DCLExample getInstance(){
        if (instance==null){
            synchronized (DCLExample.class){
                if (instance==null){
                    instance = new DCLExample();
                }
            }
        }
        return instance;
    }
}

当我们使用 instance=new DCLExample()构建一个实例对象的时候,因为 new 这个操作并不是原子的。所以这段代码最终会被编译成 3 条指令:

  • 为对象分配内存空间
  • 初始化对象
  • 把实例对象赋值给 instance 引用

由于这是三个指令并不是原子的(如图)。 按照重排序规则,在不影响单线程执行结果的情况下,两个不存在依赖关系的指令允许重排序,也就是不一定会按照代码编写顺序来执行。

这样一来,(如图)就会导致其他线程可能拿到一个不完整的对象,也就是这个 instance已经分配了引用实例,但是这个实例的初始化指令还没执行。


解决办法就是可以在 instance 这个变量上增加一个 volatile 关键字修饰,volatile 底层使用了内存屏障机制来避免指令重排序。

相关推荐
上海云盾-高防顾问5 分钟前
DNS异常怎么办?快速排查+解决指南
开发语言·php
开发者小天10 分钟前
python安装 Matplotlib 库 安装 Seaborn 库
开发语言·python·matplotlib
wjs202411 分钟前
《Foundation 折叠列表:设计与应用解析》
开发语言
Diligently_27 分钟前
idea 中vm option 配置
java·ide·intellij-idea
短剑重铸之日31 分钟前
《Seata从入门到实战》第七章:seata总结
java·后端·seata
予枫的编程笔记34 分钟前
【Kafka高级篇】避开Kafka原生重试坑,Java业务端自建DLQ体系,让消息不丢失、不积压
java·kafka·死信队列·消息中间件·消息重试·dlq·java业务开发
晞子的技术札记35 分钟前
单相Heric并网逆变器工作原理及MATLAB仿真测试
开发语言·matlab
上官-王野1 小时前
公务员暂停工伤保险
java
李云龙炮击平安线程1 小时前
Python中的接口、抽象基类和协议
开发语言·后端·python·面试·跳槽
十五年专注C++开发1 小时前
Qt deleteLater作用及源码分析
开发语言·c++·qt·qobject