zoukankan      html  css  js  c++  java
  • 双重检测单例模式中使用volatile的原因

    以前一直没在意双重检测单例模式中volatile的作用,最近又注意到了它的细节处的作用,在这里记录下。虽然现在单例模式的最佳选择是使用枚举,但通过这个增长知识也是不错的。下面是一般的双重检测单例模式的代码:

    public class Single {
        private static volatile Single instance = null;
    
        public static Single getInstance(){         //1
            if (null == instance){                   //2
                synchronized (Single .class){       //3
                    if (null == instance){             //4 
                        instance = new Single ();       //5
                    }
                }
            }
            return instance;                        //6
        } 
    }

    看起来好像没有必要使用volatile保证instance的可见性,因为  instance = new Single (); 这行是在synchronized里面的。但是这里的volatile并不是为了保证可见性的,而是为了防止指令重排造成返回的  instance 不正确的情况发生。

    看line 5代码: instance = new Single ();对象的创建实际包含一下几步:

        1. 类是否已经加载,没加载就加载类 ; 2. 申请内存; 3 初始化内存(置0,null等等);4. 执行构造方法,初始化对象; 5. 将生成的对象赋给引用

    问题就在于这几步指令是可能重排的,比如1 2 3 4 5,变成1 2 3 5 4。也就是说还没有执行构造方法将这个对象的属性初始化,各个属性都是默认值,就将这个对象赋给了引用instance了。假设有个线程A发生了上面说的情况,生成对象时执行了1 2 3 5步,这时候有个线程B执行line2发现instance不为null了,于是直接执行line6将还未执行构造方法的对象返回。因此为了万无一失,还是要使用volatile的,防止生成对象时第4步和第5步顺序颠倒。

  • 相关阅读:
    《礼物》
    第三讲.线性表(读书笔记)
    UI第十四讲(上) UI高级可视化设计 (XIB, Storyboard, AutoLayout, SIzeClass )
    UI第十三讲 UITabBarController(标签视图控制器) Block块传值
    UI第十二讲 通讯录实战
    deepin中Tomcat添加执行权限
    deepin修改javahome不生效,一直显示openjdk解决
    deepin中idea中文乱码解决
    maven添加settings.xml使用阿里云仓库
    debian配置java环境变量
  • 原文地址:https://www.cnblogs.com/shen-qian/p/12273997.html
Copyright © 2011-2022 走看看