美文网首页
volatile关键字

volatile关键字

作者: silence_J | 来源:发表于2020-04-27 17:15 被阅读0次

    volatile的作用:

    • 保证线程可见性
      MESI缓存一致性协议
    • 禁止指令重排序(CPU)
      DCL(Double Check Lock 双重检查锁)单例;
      底层由内存屏障保证。

    1. 保证线程可见性

    java中所有线程共享堆内存,除了共享内存外,每个线程都有自己的专属区域,都有自己的工作内存。如果在共享内存中有一个值的话,当某个线程访问这个值时会copy一份到自己的工作空间中,先在自己空间中改变后再更新堆内存中的值。在这过程中其他线程可能读到未更新的值。

    在这个线程里发生的改变,不能及时反映到另外一个线程里,这就是线程之间的不可见,对这个变量值加了volatile后就能保证一个线程的改变,另外一个线程马上就能看到。CPU底层是使用MESI高速缓存一致性协议实现的。

    volatile只能让被它修饰的变量具有可见性,但不能保证具有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这个操作同样存在线程安全问题。

    2. 禁止指令重排序

    指令重排:参考该篇CPU乱序执行一节

    volatile 底层是使用内存屏障实现的,在写操作和读操作前后都加了屏障。(JVM要求这样实现,是一种规范,底层用Lock指令实现)

    JVM层面上:

    StoreStoreBarrier
    volatile 写操作(Store)
    StoreLoadBarrier

    LoadLoadBarrier
    volatile 读操作(Load)
    LoadStoreBarrier

    DCL单例

    参考懒汉式单例 写法3:Singleton单例模式 代码在下方贴出

    在这个写法中是需要加volatile的,因为要防止指令重排。

    第一个线程INSTANCE = new Mgr04() 经过编译器编译后的指令分为3步:
    (1)给指令申请内存
    (2)初始化成员变量
    (3)把这块内存的内容赋值给INSTANCE。
    指令重排后可能还没初始化就已经执行了(3),这时第二个线程过来判断INSTANCE不为null就会直接return INSTANCE,初始化错误。

    加了volatile后防止了指令重排,一定能保证INSTANCE按顺序正常初始化。

    ps:不加volatile实际上也很难碰到这种问题,但为了完全正确是应该加上的。

    public class Mgr04 {
    
        private static volatile Mgr04 INSTANCE;
    
        // 构造方法私有化
        private Mgr04() {};
    
        // 该方法被调用时才创建实例
        public static Mgr04 getInstance() {
            if ( INSTANCE == null) {
                // 双重检查   如果是单次检查,仍有可能有多个线程进入if判断
                synchronized (Mgr04.class) {
                    if ( INSTANCE == null ) {
                        INSTANCE = new Mgr04();
                    }
                }
            }
            return INSTANCE;
        }
    
        // 其它方法
        public void m(){};
    
    }
    

    总结

    volatile保证线程的可见性,同时防止指令重排序。
    线程可见性在CPU级别是用MESI缓存一致性协议来保证的。
    禁止指令重排序CPU级别是禁止不了的,那是CPU内部运行过程能提高效率。
    但是在虚拟机级别加volatile后可以禁止指令重排,它内部是加了读屏障和写屏障,这是CPU的原语。

    相关文章

      网友评论

          本文标题:volatile关键字

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