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

相关推荐
Coder_preston几秒前
Spring/Spring Boot实战:从入门到项目部署
java·spring boot·spring
山岚的运维笔记5 分钟前
SQL Server笔记 -- 第16章:MERGE
java·笔记·sql·microsoft·sqlserver
阿猿收手吧!6 分钟前
【C++】深入理解C++ Atomic内存序:解决什么问题?怎么用?
开发语言·c++
小白学大数据10 分钟前
Python爬虫实现无限滚动页面的自动点击与内容抓取
开发语言·爬虫·python·pandas
Andy Dennis11 分钟前
一文漫谈设计模式之创建型模式(一)
java·开发语言·设计模式
兩尛11 分钟前
c++遍历容器(vector、list、set、map
开发语言·c++
belldeep12 分钟前
Java:Tomcat 9 和 mermaid.min.js 10.9 上传.csv文件实现 Markdown 中 Mermaid 图表的渲染
java·tomcat·mermaid·去除flexmark
£漫步 云端彡13 分钟前
Golang学习历程【第十三篇 并发入门:goroutine + channel 基础】
开发语言·学习·golang
2301_7903009618 分钟前
C++与Docker集成开发
开发语言·c++·算法
AutumnorLiuu19 分钟前
C++并发编程学习(二)—— 线程所有权和管控
java·c++·学习