Java Volatile关键字


1. Volatile

1.1 基本概念

内存可见性

内存可见性,指的是线程之间的可见性,当一个线程修改了共享变量时,另一个线程可以读取到这个修改后的值。

在这里插入图片描述

重排序

为优化程序性能,对原有的指令执行顺序进行优化重新排序。重排序可能发生在多个阶段,比如编译重排序、CPU重排序。

1.2 volatile的内存语义

  • 保证变量的内存可见性
  • 禁止volatile变量与普通变量重排序

内存可见性

public class VolatileExample {
    int a = 0;
    volatile boolean flag = false;

    public void write(){
        a = 1;         // step 1
        flag = true;  // step 2
    }
    public void reader(){
        if (flag){  // step 3
            System.out.println(a);
        }
    }
}

所谓内存可见性,指的是当⼀个线程对 volatile 修饰的变量进⾏写操作(⽐如step 2)时,JMM会立即把该线程对应的本地内存中的共享变量的值刷新到主内存;当⼀个线程对 volatile 修饰的变量进⾏读操作(⽐如step 3)时,JMM会把⽴即该线程对应的本地内存置为⽆效从主内存中读取共享变量的值。

禁止重排序

JSR-133专家组决定增强volatile的内存语义:严格限制编译器和处理器对volatile变量与普通变量的重排序。

编译器还好说,JVM是怎么还能限制处理器的重排序的呢?它是通过内存屏障来实现的。

什么是内存屏障?硬件层面,内存屏障分两种:读屏障(Load Barrier)和写屏障 (Store Barrier)。内存屏障有两个作⽤:

  1. 阻⽌屏障两侧的指令重排序;
  2. 强制把写缓冲区/⾼速缓存中的脏数据等写回主内存,或者让缓存中相应的数据失效。

编译器在⽣成字节码时,会在指令序列中插⼊内存屏障来禁⽌特定类型的处理器重排序。编译器选择了⼀个⽐较保守的JMM内存屏障插⼊策略,这样可以保证在任何处理器平台,任何程序中都能得到正确的volatile内存语义。这个策略是:

  • 在每个volatile写操作前插⼊⼀个StoreStore屏障;
  • 在每个volatile写操作后插⼊⼀个StoreLoad屏障;
  • 在每个volatile读操作后插⼊⼀个LoadLoad屏障;
  • 在每个volatile读操作后再插⼊⼀个LoadStore屏障。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值