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

相关推荐
leo__5205 分钟前
MHT多假设跟踪算法(Multiple Hypothesis Tracking)MATLAB实现
开发语言·算法·matlab
燃于AC之乐5 分钟前
深入解剖STL RB-tree(红黑树):用图解带入相关复杂操作实现
开发语言·c++·stl·红黑树·大厂面试·图解·插入操作
dawudayudaxue6 分钟前
Eclipse安卓环境配置
android·java·eclipse
a1117767 分钟前
堆叠式流程图编辑器(html 开源)
开发语言·前端·javascript·开源·编辑器·html·流程图
iPadiPhone8 分钟前
性能优化的“双刃剑”:MySQL 查询缓存深度架构解析与面试复盘
java·后端·mysql·缓存·面试·性能优化
兆子龙8 分钟前
ahooks useDebounce 与 useThrottle:防抖节流的最佳实践
java·javascript
new code Boy12 分钟前
JavaScript转Python”的速查表
开发语言·javascript·python
老友@15 分钟前
云计算的统一心智模型
开发语言·ci/cd·docker·云计算·k8s·perl
Elnaij18 分钟前
从C++开始的编程生活(19)——set和map
开发语言·c++
毕设源码-郭学长19 分钟前
【开题答辩全过程】以 环保公益网站为例,包含答辩的问题和答案
java