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

相关推荐
nanxun88613 小时前
记一次诡异的 Docker 容器"串包"故障排查
java
用户15630681035116 小时前
Day01 | Java 基础(Java SE)
java
行者全栈架构师17 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师21 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_021 小时前
mac(m5)平台编译openjdk
java
唐青枫2 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马2 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261352 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户3721574261352 天前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454753 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程