内存屏障(cpu内存屏障 与java内存屏障)

2023-10-27

CPU 内存屏障

定义

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

读写屏障指令

指令1 :sfence 写屏障 在sfence 指令前的写操作 必须在sfence 指令的写操作前完成。
指令2: lfence 读屏障 在lfence指令前的读操作 必须在lfence指令的读操作前完成。
指令3:mfence 读写屏障 在mfence 指令的读写操作 必须在mfence指令的读写操作前完成。

为什么会出现内存屏障

内存屏障存在的意义就是为了解决程序在运行过程中出现的内存乱序访问问题,内存乱序访问行为出现的理由是为了提高程序运行时的性能。

java内存屏障

java内存屏障存在意义

每个CPU都会有自己的缓存,缓存的目的就是为了提高性能,避免每次都要向内存取。但是这样的弊端也很明显:不能实时的和内存发生信息交换,分在不同CPU执行的不同线程对同一个变量的缓存值不同。
在Java中通过用volatile关键字修饰变量,Synchronized关键字包住的代码区域的方法,来解决上述问题,通过屏蔽这些差异,统一由jvm来生成内存屏障的指令。

java中内存屏障的主要类型

不同硬件实现内存屏障的方式不同,Java内存模型屏蔽了这种底层硬件平台的差异,由JVM来为不同的平台生成相应的机器码。
Java内存屏障主要有Load和Store两类。
对Load Barrier来说,在读指令前插入读屏障,可以让高速缓存中的数据失效,重新从主内存加载数据
对Store Barrier来说,在写指令之后插入写屏障,能让写入缓存的最新数据写回到主内存

对于Load和Store,在实际使用中,又分为以下四种:

LoadLoad 屏障

序列:Load1,Loadload,Load2
确保Load1所要读入的数据能够在被Load2和后续的load指令访问前读入。通常能执行预加载指令或/和支持乱序处理的处理器中需要显式声明Loadload屏障,因为在这些处理器中正在等待的加载指令能够绕过正在等待存储的指令。 而对于总是能保证处理顺序的处理器上,设置该屏障相当于无操作。

StoreStore 屏障

序列:Store1,StoreStore,Store2
确保Store1的数据在Store2以及后续Store指令操作相关数据之前对其它处理器可见(例如向主存刷新数据)。通常情况下,如果处理器不能保证从写缓冲或/和缓存向其它处理器和主存中按顺序刷新数据,那么它需要使用StoreStore屏障。

LoadStore 屏障

序列: Load1; LoadStore; Store2
确保Load1的数据在Store2和后续Store指令被刷新之前读取。在等待Store指令可以越过loads指令的乱序处理器上需要使用LoadStore屏障。

StoreLoad 屏障

序列: Store1; StoreLoad; Load2
确保Store1的数据在被Load2和后续的Load指令读取之前对其他处理器可见。StoreLoad屏障可以防止一个后续的load指令 不正确的使用了Store1的数据,而不是另一个处理器在相同内存位置写入一个新数据。正因为如此,所以在下面所讨论的处理器为了在屏障前读取同样内存位置存过的数据,必须使用一个StoreLoad屏障将存储指令和后续的加载指令分开。Storeload屏障在几乎所有的现代多处理器中都需要使用,但通常它的开销也是最昂贵的。它们昂贵的部分原因是它们必须关闭通常的略过缓存直接从写缓冲区读取数据的机制。这可能通过让一个缓冲区进行充分刷新(flush),以及其他延迟的方式来实现。

Synchronized 锁

通过 Synchronized关键字包住的代码区域,当线程进入到该区域读取变量信息时,保证读到的是最新的值.这是因为在同步区内对变量的写入操作,在离开同步区时就将当前线程内的数据刷新到内存中,而对数据的读取也不能从缓存读取,只能从内存中读取,保证了数据的读有效性.这就是插入了StoreStore屏障

volatile语义中的内存屏障

volatile的内存屏障策略非常严格保守,非常悲观且毫无安全感的心态:

在每个volatile写操作前插入StoreStore屏障,在写操作后插入StoreLoad屏障;
在每个volatile读操作前插入LoadLoad屏障,在读操作后插入LoadStore屏障;

由于内存屏障的作用,避免了volatile变量和其它指令重排序、线程之间实现了通信,使得volatile表现出了锁的特性。
volatile与synchronized对比
volatile变量修饰符如果使用恰当的话,它比synchronized的使用和执行成本会更低,因为它不会引起线程上下文的切换和调度

final语义中的内存屏障

对于final域,编译器和CPU会遵循两个排序规则:

新建对象过程中,构造体中对final域的初始化写入和这个对象赋值给其他引用变量,这两个操作不能重排序;
初次读包含final域的对象引用和读取这个final域,这两个操作不能重排序;(晦涩,意思就是先赋值引用,再调用final值)

总之上面规则的意思可以这样理解,必需保证一个对象的所有final域被写入完毕后才能引用和读取。这也是内存屏障的起的作用:

写final域:在编译器写final域完毕,构造体结束之前,会插入一个StoreStore屏障,保证前面的对final写入对其他线程/CPU可见,并阻止重排序。
读final域:在上述规则2中,两步操作不能重排序的机理就是在读final域前插入了LoadLoad屏障。

X86处理器中,由于CPU不会对写-写操作进行重排序,所以StoreStore屏障会被省略;而X86也不会对逻辑上有先后依赖关系的操作进行重排序,所以LoadLoad也会变省略。

本文参考文献
内存屏障
java内存屏障的原理与应用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内存屏障(cpu内存屏障 与java内存屏障) 的相关文章

随机推荐

  • J2EE&通用分页02

    目录 一 重构 提取公用方法 1 为了进行公共方法的抽取 需要找出上面实习中的可通用部分 和差异化部分 2 公用方法封装思路 3 具体实现 二 分页标签 2 1 准备一个Servlet 3 2 结果展示页面 三 过滤器解决中文乱码问题 四
  • 董事长、总裁和CEO--浅谈公司领导者的称谓与实质

    自从信息产业兴起以来 尤其是网络股泡沫产生以来 CEO 在中国骤然成为一个流行词汇 总经理和总裁们纷纷改称CEO 这个缩写词比它的中译版 首席执行官 更简洁 在中国人心目中更有神圣感 于是便出现了今天CEO满天飞的局面 刚刚从大学毕业的年轻
  • MySQL视图

    一 视图 介绍及基本语法 视图 View 是一种虚拟存在的表 视图中的数据并不在数据库中实际存在 行和列数据来自定义视图的查询中使用的表 并且是在使用视图时动态生成的 通俗的讲 视图只保存了查询的SQL逻辑 不保存查询结果 所以我们在创建视
  • VUE移动端使用overflow-auto滚动条坑

    解决 滚动条 滑动 一次就一直出现在底部问题 在关闭模态框之前 操作原生dom var box document querySelector div box scrollTop 0 设置 滚动条的 位置 为 0 这样 每次重新打开另一条数据
  • 新版husky8.0配合commitlint,规范我们的git的提交记录

    文章目录 安装 配置 第一步 初始化husky 第二步 添加git提交的hook 第三步 在项目根目录新建配置文件 commitlint config js 验证一下 附1 git commit完整的规范 附2 commitlint con
  • C+复习Parameter Passing

    double average double a double b call by value void swap double a double b call by reference in C 11 this is more techni
  • 在Ubuntu环境下用gcc命令运行c程序以及Makefile编译

    在Ubuntu环境下用gcc命令运行c程序以及Makefile编译 用gcc命令编译c语言 用VC 6 0编译C语言 用Makefile编译C语言 用gcc命令编译c语言 主程序main1 c include
  • C51 数码管的动态显示 dynamic display method of digital tube

    代码 include
  • Java代码实现使用while循环接受键盘的输入,如果输入的exit就退出,否则提示用户继续输入

    import java util Scanner 需求 编写代码按照要求实现以下的功能 使用while循环接受键盘的输入 如果输入的exit就退出 否则提示用户继续输入 要点提取 用while true 控制循环输入 用break跳出循环
  • html 基本标签

    1标题标签 h1 h6 h1 这是一段文字 h1 2 段落标签 p p 自动换行 p 这是一段文字 p 3 换行标签和水平线标签 br hr 4 图像标签 img src 图片路径 用于定义html页面的图像 img src img img
  • spss数据预处理步骤_数据处理之剔除无效问卷

    我们都知道在数据分析前 首先需要对数据进行预处理 检查数据中是否含有存在无效样本 异常值等 如果同一样本中存在大量漏填数据或相似答案过多的情况这样的样本都应该算作无效样本来处理 无效样本的常见使用场景 问卷研究中乱填问卷的样本 数据库下载的
  • 动态负荷对电力系统摆幅曲线的影响研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 摆动曲线仿真是评估扰动后电力系统稳定性的重
  • Selenium成长之路-19alert/prompt/confirm弹框处理

    webdriver 中处理 JavaScript 所生成的 alert confirm 以及 prompt 是很简单的 具体思路是使用 switch to alert 方法定位到 alert confirm prompt 然后使用 text
  • 哪些行业需要连接云专线?

    在诸多行业之中 有一些行业对数据安全性要求高 业务需要实时性 业务需求复杂 往往需要建立起私密 高速 安全的传输通道 云专线是他们经常采用的方案 具体来讲 都有哪些行业需要连接云专线呢 请见下方 1 金融行业 金融行业需要进行大量的数据传输
  • 前端绘图方式Canvas和SVG的区别

    Canvas和SVG是html5中支持2种可视化技术 都是可以在画布上绘制图形和放入图片 下面来介绍和分析一下他们 一 Canvas 和 SVG 简介 1 什么是Canvas Canvas 是H5新出来的标签
  • typora快捷键大全

    typora快捷键大全 一 菜单栏 文件 alt F 编辑 alt E 段落 alt P 格式 alt O 视图 alt V 主题 alt T 帮助 alt H 二 文件 新建 Ctrl N 新建窗口 Ctrl Shift N 打开 Ctr
  • order by、sort by、distribute by和cluster by 的区别,使用场景

    在Hive中 order by sort by distribute by和cluster by是用于数据排序和分区的关键字 它们在语义和使用场景上有一些区别 1 order by order by关键字用于对查询结果进行全局排序 它会将所
  • C 语言 strftime()和strptime()

    C 语言 将时间转换为字符串和字符串转换为时间格式 首先 要先知道C语言头文件time h下的 struct tm结构体 struct tm int tm sec 秒 范围从 0 到 59 int tm min 分 范围从 0 到 59 i
  • 使用扩展卡尔曼滤波(EKF)融合激光雷达和雷达数据(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 大多数自动驾驶汽车都配备了激光雷达和雷达
  • 内存屏障(cpu内存屏障 与java内存屏障)

    文章目录 CPU 内存屏障 定义 读写屏障指令 为什么会出现内存屏障 java内存屏障 java内存屏障存在意义 java中内存屏障的主要类型 LoadLoad 屏障 StoreStore 屏障 LoadStore 屏障 StoreLoad