volatile关键字的作用


主要作用

  1. 保证共享变量可见性

  2. 防止指令重排

volatile如何禁止指令重排序的?

volatile关键字通过“内存屏障”来防止指令被重排序。
下面是基于保守策略的JMM内存屏障插入策略:

  • 在每个volatile写操作的前面插入一个StoreStore屏障
  • 在每个volatile写操作的后面插入一个StoreLoad屏障
  • 在每个volatile读操作的后面插入一个LoadLoad屏障
  • 在每个volatile读操作的后面插入一个LoadStore屏障

DCL单例模式

JDK 1.5中才完全修复volatile屏蔽指令重排序的语义,在此之前无法安全地使用DCL(双锁检测)来实现单例模式。

public class Singleton {
    private volatile static Singleton instance;

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

分析

instance = new Singleton();并不是一个原子操作。事实上,它可以”抽象“为下面几条JVM指令:
memory = allocate(); //1:分配对象的内存空间
initInstance(memory); //2:初始化对象
instance = memory; //3:设置instance指向刚分配的内存地址

当发生指令重排时,操作可能如下:
memory = allocate(); //1:分配对象的内存空间
instance = memory; //3:设置instance指向刚分配的内存地址(此时对象还未初始化)
ctorInstance(memory); //2:初始化对象

注意

volatile关键字不能保证原子性

声明:微默网|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - volatile关键字的作用


不以物喜,不以己悲! 不忘初心,方得始终!