一、认识 volatile 关键字

当一个线程读取,一个线程写入的情况下,就会存在数据的不一致性,

二、CPU 与 JMM

1、CPU Cache 模型

每一个 CPU 在修改内存数据的步骤如下:

  1. 从内存中把数据加载到 Cache 中
  2. 从 Cache 中读取数据加载到寄存器中
  3. 在寄存器中更新数据
  4. 把更新结果写入 Cache
  5. 把更新结果写入到内存中

image.png
程序的局部执行原理

解决办法
  • 总线(BUS)加锁:封装的粒度太大,效率比较低
  • MESI 协议:
    • 读操作,不做任何事情,把 Cache 中的数据读到寄存器
    • 写操作,发出信号,通知其他的 CPU 将变量的 Cache line 置为无效状态,其他的 CPU 要访问这个变量的时候,只能从内存中获取

2、JMM 内存模型

image.png

  • 主内存中的数据是所有线程都可以访问的
  • 每个线程都有自己的工作空间
  • 工作空间中的数据:局部变量、主内存的副本
  • 线程不能直接修改内存中的数据,只能读到工作空间来进行修改,修改完成后,刷新到主内存

三、volatile 语义分析

当变量使用 volatile 关键字修饰时,当某一个线程修改这个变量时,会发出 JMM 控制信号(相当于设置了 Cache line 无效),那么其他线程要读取整个变量的时候,就只能从主内存中读取,那么问题来了,volitail 也不能保证数据的一致性(原子性)

1、保证可见性

  • volatile 作用:让其他线程能够马上感知到某一线程对某个变量的修改
  • 不能保证原子性

2、保证有序性

在编译和指令优化阶段,在输入的代码顺序并不一定是程序实际执行的顺序,这就叫做指令重排(为了提高 CPU的吞吐量)。指令重排必须保证结果不发生变化

  • 单线程的情况下,指令重排后没有影响(as-if-serial)
  • 多线程的情况下,可能造成影响

当使用 volatile 关键字的时候,可以保证指令按照程序的顺序执行,volatile 的规则如下:

  • volatile 之前的代码不允许调整到它的后面
  • volatile 之后的代码不允许调整到它的前面

四、volatile 实现原理和机制

volatile 的实现其实就是锁的原理(轻量级锁)

  1. volatile int a; ==> LOCK: a

五、volatile 与 synchronized 的区别

  • 使用上的区别:volatile 只能修饰变量synchronized 可以修饰方法代码块
  • 对原子性的保证:volatile 不能保证原子性synchronized 可以保证原子性
  • 对可见性的保证:都可以保证可见性,但实现原理不同,volatile 使用 LOCK 来实现,synchronized 使用的是 monitor 来实现(monitorenter 和 monitorexit)
  • 对有序性的保证:volatile 能保证有序性,synchronized 也可以保证有序性,但是代价太大(重量级锁会退化到串行)
  • 其他:volatile **不会引起线程阻塞synchronized 会引起线程阻塞**

六、volatile 的使用场景

  • 状态(开关)模式
  • 双重检查锁定 DCL(Double-Checked-Locking):如单例模式的应用 volatile + synchronized
  • 需要利用顺序性

七、volatile 重排序规则

是否能重排序 第二个操作
第一个操作 普通读/写 volatile读 volatile写
普通读/写 NO
volatile 读 NO NO NO
volatile 写 NO NO

结论:
1、第二个操作是 volatile 写,不管第一个操作是什么,都不会重排序
2、第一个操作是 volatile 读,不管第二个操作是什么,都不会重排序
3、第一个操作是 volatile 写,第二个操作时 volatile 的话,也不会发生重排序

X86 处理器不会对 读-读,读-写,写-写 操作做重排序,会省略掉这三类操作的内存屏障,仅会对写-读做重排序,所以 volatile 写-读操作只需要在 volatile 后面加一个 StoreLoad 屏障

JVM 内存屏障插入策略
1、在每个 volatile 写操作的前面插入一个 StroeStroe 屏障
2、在每个 volatile 写操作的后面插入一个 StroeLoad 屏障
3、在每个 volatile 读操作的后面插入一个 LoadLoad 屏障
4、在每个 volatile 读操作的后面插入一个 LoadStore 屏障