美文网首页
volatile详解(二)(重排序)

volatile详解(二)(重排序)

作者: iMikasa_ | 来源:发表于2021-08-30 21:59 被阅读0次

    volatile保证线程安全可见性——volatile详解(一)

    禁止重排序、防止代码重排序是volatile关键字的作用之一

    什么是指令重排序

    public void set() {
        int a=1;
        int b=2;
    }
    

    CPU为了提供程序执行效率,会对指令执行顺序进行重排,以上代码,b赋值可能先于a赋值执行。
    但以下代码不会涉及指令重排,因为b赋值依赖于a。

    public void set() {
        int a=1;
        int b=a;
    }
    

    指令重排序所带来的问题

    对于单线程来说,指令重排会提高CPU执行效率,基本上没有任何问题,但对于多线程,重排会导致指令执行的不确定性。

    举个例子,下面是经典的懒汉单例模式

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

    分析:
    先要了解对象的构造过程,实例化一个对象其实可以分为三个步骤:

    • 分配内存空间。
    • 初始化对象。
    • 将内存空间的地址赋值给对应的引用

    但是由于操作系统可以对指令进行重排序,所以上面的过程也可能会变成如下过程:

    • 分配内存空间。
    • 将内存空间的地址赋值给对应的引用。
    • 初始化对象

    如果是这个流程,多线程环境下就可能将一个未初始化的对象引用暴露出来,从而导致不可预料的结果。因此,为了防止这个过程的重排序,我们需要将变量设置为volatile类型的变量。

    相关文章

      网友评论

          本文标题:volatile详解(二)(重排序)

          本文链接:https://www.haomeiwen.com/subject/ylzoiltx.html