volatile详解(二)(重排序)

2021-08-30  本文已影响0人  iMikasa_

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类型的变量。

上一篇下一篇

猜你喜欢

热点阅读