特性

  1. 可以保证不同线程对共享变量的可见性
  2. 可以禁止指令重排(有序性)
  3. 对于复合操作不可以保证原子性

    可见性

    指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

    指令重排

    见:指令重排

    内存语义

  • volatile写的内存语义: 当写一个volatile变量时,JMM会把该线程对应的本地内存中的所有共享变量值刷新到主内存
  • volatile读的内存语义:当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取所有共享变量。

    内存语义的实现——内存屏障指令(即如何实现可见性和有序性?)

    java 编译器在生成指令序列的适当位置会插入内存屏障指令内存屏障(Memory Barrier)来禁止特定类 型的处理器重排序,从而让程序按我们预想的流程去执行。

  • 写操作:在其前后分别加上 StoreStore 和 StoreLoad指令

volatile 关键字 - 图1

  • 读操作:在其后加上 LoadLoad 和 LoadStore指令

volatile 关键字 - 图2
通俗的理解:

  • volatile写,分别通过storestore(防止和之前的写重排),stroeload(防止和之后的读重排)
  • volatile读,分别通过loadload(防止和之后的读重排),loadstore(防止和之后的写重排)

由此可看到:

  • 内存屏障是可以保证volatile变量前后读写顺序的(可保证有序性);
  • 写操作时,使用store指令会强制线程刷新数据到主内存,读操作使用load指令会强制从主内存读取变量值(保证可见性)。