volatile 关键字


前置概念

  • 指令重排:JVM 为了优化指令、提高运行速度,在不影响单线程执行结果的前提下,会对代码进行重排。
  • 内存可见性:每个线程在获取锁之后,会在自己的工作内存中操作共享变量,操作完成之后将工作内存中的副本写回内存,在此过程中共享变量的变化对其是不可见的。这样做也是为了提高效率。

volatile 关键字的作用

  • 防止指令重排;
    • 线程中的每一个操作 happens-before 这个线程中在程序顺序中后面出现的每一个操作
    • 对监视器的解锁 happens-before 同一监视器上的所有后续锁定
    • 对 volatile 字段的写 happens-before 同一 volatile 的每一个后续读
    • 对一个线程的 Thread.start() 调用 happens-before 在启动的线程中的所有操作
    • 线程中的所有操作 happens-before 从这个线程的 Thread.join() 成功返回的所有其他线程
  • 保证每次访问变量都会刷新。

    保证 volatile 字段的读写直接在主存而不是寄存器或者本地处理器缓存中进行,并且代表线程对 volatile 变量进行的这些操作是按线程要求的顺序进行的。

这样 volatile 就提供了一个轻量级的锁机制。

注意

  • 已经用 synchronize 关键字加锁的变量不需要 volatile 修饰。
  • 非原子操作如 i++,需要用 synchronize 关键字同步。

参考

volatile关键字的作用、原理

Java并发:volatile内存可见性和指令重排

修复 Java 内存模型,第 2 部分