内存屏障1
创始人
2024-05-26 04:09:23
0

内存屏障

引入

我们知道 volatile 能保证 JMM约束的 可见性和有序性。

关于有序性,到底该如何理解?

有序性的根本保证,就是 禁止指令重排序

重排序

重排序是指 编译器和处理器 为了优化程序性能 而对指令序列进行重新排序的一种手段,有时候会改变程序语句的先后顺序。

  • 不存在数据依赖关系,可以重排序
  • 存在数据依赖关系,禁止重排序
    但是重排序后的指令,绝不能改变原有的串行语义,这点在并发编程中 重点考虑

概念

内存屏障
也称为内存栅栏,屏障指令等,是一类同步屏障指令 ,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后,才可以执行此点之后的操作。避免了代码重排序。

内存屏障其实是一种JVM指令,java内存模型的重排规则会要求Java编译器在生成JVM指令时 插入特定的内存屏障指令,通过这些内存屏障指令,volatile实现了java内存模型中的可见性和有序性(禁止重排序),但Volatile无法保证原子性。

  • 内存屏障之前的所有写操作 都要写回到主内存
  • 内存屏障之后的所有读操作 都能获得内存屏障之前的所有写操作的最新结果(实现可见性)
写屏障(Store Memory Barrier): 告诉处理器在写屏障之前将所有存储在缓存(store bufferes)中的数据同步到主内存。也就是说当看到Store屏障指令,就必须把该指令之前所有写入指令执行完毕才能继续往下执行。
读屏障(Load Memory Barrier): 处理器在读屏障之后的读操作,都在读屏障之后执行。也就是说在Load屏障指令之后就能够保证后面的读取数据指令一定能够读取到最新的数据。

因此重排序时,不允许把内存屏障之后的指今重排序到内存屏障之前。一句话,对一个volatie变量的写,先行发生于任意后续对这个volatile变量的读,也叫写后读


内存屏障的分类

前文介绍的 happens-before 先行发生原则,类似接口规范,那么 我们如何对此规范进行落地实现?

实现它的 就是 内存屏障

内存屏障 可以分为 读屏障 (Load Barrier)写屏障(Store Barrier)

  • 读屏障 (Load Barrier)
    在读指令之前插入读屏障,让工作内存或CPU高速缓存当中的缓存数据失效,重新回到主内存中获取最新数据
  • 写屏障(Store Barrier)
    在写指令之后插入写屏障,强制把写缓冲区的数据刷回到主内存中

我们对这个屏障进行源码分析 看看它到底是什么样子的
源码下载连接如下:
openJDK8u


unsafe.class
在这里插入图片描述
在这里插入图片描述

OrderAccess.hpp
在这里插入图片描述

屏障的真实底层处理内容 是汇编语句
在这里插入图片描述

对二者进一步划分 可以划分为:

  • 读读屏障(LoadLoad)
  • 读写屏障(LoadStore)
  • 写写屏障(StoreStore)
  • 写读屏障(StoreLoad)
屏障类型指令类型说明
loadLoadLoad1;LoadLoad;Load2保证load1的读取操作在 load2及后续读取操作之前执行
StoreStoreStore1;storeStore;Store2在store2及其以后的写操作执行前,保证store1的写操作已经刷新到主内存
LoadStoreLoad;LoadStore;Store2在store2及以后的写操作执行前,保证load1的读操作已读取结束
StoreLoadStore1;StoreLoad;Loaded保证store1的写操作已经刷新到主内存之后,load2及以后的读操作才能执行

我们整理一下 关于JMM、重排序的思路

  1. 重排序有可能影响程序的执行和实现,因此,我们有时候希望告诉JVM你别“自作聪明”给我重排序,我这里不需要排序,听主人的。
  2. 对于编译器的重排序,JMM会根据重排序的规则,禁止特定类型的编译器重排序。(happen-before)
  3. 对于处理器的重排序,Java编译器在生成指令序列的适当位置,插入内存屏障指令,来禁止特定类型的处理器排序。

我们通过一个Demo 来更具象的理解:

/*** @Title:* @Description: TODO* @author: Alex* @Version:* @date 2023-02-17-0:43*/
public class FenceDemo {volatile static int a = 1;public static void main(String[] args) {new Thread(() -> {while (true) {//第一个操作是volatile读System.out.println(Thread.currentThread().getName() + "\t" +" get a value before every operations= " + a);if (a > 1) {//第三个操作是volatile读System.out.println(Thread.currentThread().getName() + "\t" +"second get a value = " + a); //loadbreak;}}}, "t1").start();new Thread(() -> {synchronized (FenceDemo.class) {//第二个操作是 volatile写  之间存在内存屏障 LoadStore 不能发生指令重排a++;  //store (存在间隙 注意非原子性)}}, "t2").start();}
}

输出结果如下:

t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	 get a value before every Load= 1
t1	second get a value = 2

这个例子符合了我们预想的,

  1. 先读读看a 的值是 多少? load1
  2. 修改a的值 store2
  3. 判定a>1 再次去执行 读操作 load3

load 1       //volatile读操作
LoadStore      读写屏障 保证先读到初值,而不是被修改后的值(防止load1被重排)
store2      //volatile 写操作
StoreLoad     //写读屏障 防止后续读操作,读到未被正确修改的值
load3     //volatile读操作

形象的总结:
一锅汤,我先尝尝咸淡(load1) ,味道淡了,加点盐(store2), 再去常常咸淡(load3)

这样一系列操作,也是符合常理的,如果先加盐,再尝咸淡,那就离谱了。

下一步,我们加深案例难度:
如果出现普通读呢?

//TODO
01点34分 2023年2月17日

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...