volatile

 


从单例模式引出

单例模式一文中,DCL实现单例使用了关键了volatile:

class Singleton5 {

    private Singleton5() {
        System.out.println("private Singleton3");
    }

    private static volatile Singleton5 INSTANCE = null; 

    public static Singleton5 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton5.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton5();  // *
                }
            }
        }
        return INSTANCE;
    }

}

*处的代码反编译后的字节码指令为:

1: new              // 给Singleton5这个对象分配空间
2: invokespecial    // Method "<init>":()V  执行构造函数
3: putstatic        // 将内存空间的地址赋值给对应的引用,也就是这里的INSTANCE

由于2和3这两个指令并没有依赖关系,所以CPU在执行的时候可能会发生指令重排序,即以这种顺序执行:

1: new              // 给Singleton5这个对象分配空间
3: putstatic        // 将内存空间的地址赋值给对应的引用,也就是这里的INSTANCE
2: invokespecial    // Method "<init>":()V  执行构造函数

那么假设现在有两个线程执行这段代码,并且按照顺序执行:

线程1                    线程2

new 分配空间
INSTANCE = 对象
                        if (INSTANCE == null)
                        return INSTANCE
Singleton5() 初始化

这样线程2拿到的对象就是没有初始化过对象,可能会出现问题。









说明

===================================

仅作为校招时的《个人笔记》,详细内容请看【参考】部分

===================================

参考

  1. B站,黑马满老师
  2. 《深入理解Java虚拟机》第3版
posted @   optimjie  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示