• 双重校验锁为什么要用volatile修饰


    public class Singleton {  
        private volatile static Singleton singleton;  
        private Singleton (){}  
        public static Singleton getSingleton() {  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
            if (singleton == null) {  
                singleton = new Singleton();  
            }  
            }  
        }  
        return singleton;  
        }  
    }

    在编写单例模式懒加载时,都会加上volatile修饰,为什么需要加上volatile呢?

    这里我们需要提到指令重排序,什么是指令重排序呢?

    https://blog.csdn.net/weixin_34037977/article/details/88024601

    我们创建对象的时候流程是这样滴

    1 加载指定的字节码文件进内存
    2 通过new在堆中开辟空间,分配首地址。
    3 对对象的属性进行默认初始化。
    4 调用与之对应的构造函数,构造函数压栈。
    5 构造函数中执行隐式的super()语句,访问父类的构造函数。
    6 对对象的属性进行显示初始化。
    7 调用类中的构造代码块。
    8 执行构造函数中自定义的初始化代码。
    9 初始化完毕,将地址赋值给指定的引用。

    在重排序后,9就不能保证是在最后一步执行

    当两条线程进来时,线程A在执行singleton = new Singleton(),这时线程B在判断singleton == null,因为重排序的原因,他判断singleton不为null。但实际上线程B此时拿到的是一个不完整的对象。

    因此我们需要使用volatile来禁止指令重排序优化,从而安全的实现单例。

  • 相关阅读:
    DjangoORM更新操作、查询方式与优化
    uniapp 打电话功能的几种方式
    liveserver 安装和运行:
    django的ORM中get方法异常,**(双星号)
    Django的DRF
    java中枚举类常见用法
    Oracle数据库备份和还原
    node.js安装教程
    node.js安装下载
    java中数据匹配
  • 原文地址:https://www.cnblogs.com/nicori/p/11698240.html
Copyright © 2020-2023  润新知