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

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 并发编程系列之volatile内存语义

前言

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

volatile的特性

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

  • **可见性**:对一个volatile变量的读,总是能看到对这个volatile变量最后的写入结果,就是保证最后一次的写入操作一定发生在读操作之前;
  • **原子性**:对任意单个volatile变量的读-写具有原子性,但是对于volatile++这种复合操作就不保证其原子性了;
  • 原子性:对任意单个volatile变量的读-写具有原子性,但是对于volatile++这种复合操作就不保证其原子性了;

    volatile写-读的内存语义

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

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

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

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

    volatile内存语义的实现

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

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

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

  • 在每个volatile写操作的前面插入一个StoreStore屏障。这个屏障可以禁止上面的普通写和下面的volatile写发生重排序
  • 在每个volatile写操作的后面插入一个StoreLoad屏障。该屏障可以防止上面的volatile写与下面的volatile读或写操作发生重排序
  • 在每个volatile读操作的后面插入一个LoadLoad屏障。该屏障可以禁止下面所有的普通读操作与上面的volatile读发生重排序
  • 在每个volatile读后面插入一个LoadStore屏障,该屏障可以禁止下面所有的普通写和上面的volatile读发生重排序

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

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

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

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

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

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

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

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

    原文始发于微信公众号(Justin的后端书架):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> 并发编程系列之volatile内存语义


     上一篇
    并发编程系列之Final域的内存语义 并发编程系列之Final域的内存语义
    前言 上节我们讲了锁的内存语义,在同步原语中我们已经讲了两个,今天再来介绍另一个同步原语Final域,了解下final域的内存语义以及重排序规则在处理器中又是如何实现的,并结合前面的volatile和锁,大家可以进行对比下,OK,开始我们今
    2021-04-05
    下一篇 
    并发编程JMM系列之重排序和顺序一致性 并发编程JMM系列之重排序和顺序一致性
    前言 昨天我们接触到了什么是Java内存模型以及两种Java并发模型,并对JMM有了一些初步的认识和了解,我们在上节有提到JMM的重排序规则,但是讲的不详细,今天我们再重点聊下重排序这个东西,以及顺序一致性内存模型,OK,开始我们今天的并发
    2021-04-05