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

相关推荐
Ustinian_31033 分钟前
【C/C++】For 循环展开与性能优化【附代码讲解】
c语言·开发语言·c++
牵牛老人43 分钟前
Qt 插件开发全解析:从接口定义,插件封装,插件调用到插件间的通信
开发语言·qt
钮钴禄·爱因斯晨1 小时前
AIGC浪潮下,风靡全球的Mcp到底是什么?一文讲懂,技术小白都知道!!
开发语言·人工智能·深度学习·神经网络·生成对抗网络·aigc
22jimmy2 小时前
JavaWeb(二)CSS
java·开发语言·前端·css·入门·基础
机器视觉知识推荐、就业指导4 小时前
面试问题详解五:Qt 信号与槽的动态管理
开发语言·qt
vvilkim5 小时前
Java主流框架全解析:从企业级开发到云原生
java·运维·云原生
MZ_ZXD0016 小时前
springboot汽车租赁服务管理系统-计算机毕业设计源码58196
java·c++·spring boot·python·django·flask·php
A 计算机毕业设计-小途6 小时前
大四零基础用Vue+ElementUI一周做完化妆品推荐系统?
java·大数据·hadoop·python·spark·毕业设计·毕设
岁忧8 小时前
(nice!!!)(LeetCode 每日一题) 679. 24 点游戏 (深度优先搜索)
java·c++·leetcode·游戏·go·深度优先
四维碎片10 小时前
【Qt】线程池与全局信号实现异步协作
开发语言·qt·ui·visual studio