Volatile的内存语义

内存语义

内存语义指的是:
在多线程或处理器中用来控制存取共享内存位置,或者说是在更高层次上共享变量的处理逻辑。

volatile的happens-before原则

volatile变量原则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。

volatile的内存语义

volatile的内存语义即是用来保证volatile的happens-before原则。

  • volatile写:当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。


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


  • 线程A写一个volatile变量,实质上是线程A向接下来将要读这个volatile变量的某个线程发出了(其对共享变量所做修改的)消息。

  • 线程B读一个volatile变量,实质上是线程B接收了之前某个线程发出的(在写这个volatile变量之前对共享变量所做修改的)消息。

  • 线程A写一个 volatile变量,随后线程B读取这个volatile变量,这个过程实质上是线程A通过主内存向线程B发送消息。

volatile内存语义的实现

为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。

内存屏障是一种barrier指令类型,它导致CPU或编译器对barrier指令前后发出的内存操作执行顺序约束。也就是说,在barrier之前的内存操作保证在barrier之后的内存操作之前执行。

内存屏障有以下4种:

  • LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
  • StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
  • LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
  • StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。 在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。

为了实现volatile内存语义,Java编译器会这样使用内存屏障:


内存屏障 ---实现---> 内存语义 ---保证---> happens-before原则

参考资料

  • Memory Semantic
  • Memory Barrier
  • 《Java并发编程艺术》第三章
  • https://www.cnblogs.com/chenyangyao/p/5269622.html

你可能感兴趣的:(Volatile的内存语义)