并发编程系列之volatile内存语义

前言

前面介绍顺序一致性模型时,我们提到了程序如果正确的同步就会具备顺序一致性,这里所说的同步泛指广义上的同步,其中包括就包括同步原语volatile,那么volatile声明的变量为什么就能保证同步呢?这又是如何实现的呢?今天就让我们一起来揭开这神秘的面纱,OK,开始我们今天的并发编程之旅吧。

volatile的特性

volatile特性可以理解为对volatile变量的单个读写,看成是使用了同一个锁对这些单个读写进行了同步,他们之间的执行效果是一样的;volatile变量自身具有下面2种特性:

可见性:对一个volatile变量的读,总是能看到对这个volatile变量最后的写入结果,就是保证最后一次的写入操作一定发生在读操作之前;

原子性:对任意单个volatile变量的读-写具有原子性,但是对于volatile++这种复合操作就不保证其原子性了;

volatile写-读的内存语义

volatile写内存语义:当写一个volatile变量时,JMM会把线程对应的本地内存中的共享变量值刷新到主内存,如下图所示:

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

volatile内存语义的实现

接下来我们再看看volatile在JMM中是如何实现的,首先看下面这张volatile重排序规则表:

NO表示不允许进行重排序,例如当第一个操作是volatile读时,就不允许重排序,为了实现volatile内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序,下面我们再看看JMM中内存屏障的插入策略:

在每个volatile写操作的前面插入一个StoreStore屏障。这个屏障可以禁止上面的普通写和下面的volatile写发生重排序

在每个volatile写操作的后面插入一个StoreLoad屏障。该屏障可以防止上面的volatile写与下面的volatile读或写操作发生重排序

在每个volatile读操作的后面插入一个LoadLoad屏障。该屏障可以禁止下面所有的普通读操作与上面的volatile读发生重排序

在每个volatile读后面插入一个LoadStore屏障,该屏障可以禁止下面所有的普通写和上面的volatile读发生重排序

volatile写插入内存屏障后生成的指令序列

volatile读插入内存屏障后生成的指令序列

以上就是同步原语volatile的内存语义,通过这篇文章可以了解到底层是如何保证同步的,希望你能有所收获,感谢阅读!!!

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180311G0RU0F00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券