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 底层使用了内存屏障机制来避免指令重排序。

相关推荐
空空kkk2 分钟前
Java集合——List
java
telllong2 分钟前
C++20 Modules:从入门到真香
java·前端·c++20
叫我一声阿雷吧8 分钟前
JS 入门通关手册(21):原型链:JS 继承的底层原理
开发语言·javascript·前端面试·原型链·js继承·js进阶·js面向对象
程序员小崔日记13 分钟前
一道基础计算题卡在 40 分,求助判题规则问题
java·算法·竞赛
是Yu欸14 分钟前
LangGraph 智能体状态管理与决策
java·javascript·数据库
计算机学姐14 分钟前
基于SpringBoot的中药材店铺管理系统
java·vue.js·spring boot·后端·spring·tomcat·推荐算法
猫墨*15 分钟前
springboot3、knife4j-openapi3配置动态接口版本管理
java·开发语言
weixin_5316518115 分钟前
Python 渐进式学习指南
开发语言·windows·python
愣头不青16 分钟前
543.二叉树的直径
java·算法
weixin_6495556717 分钟前
C语言程序设计第四版(何钦铭、颜晖)第八章指针之在数组中查找指定元素
c语言·开发语言