必须了解的内存屏障

news2024/11/27 14:52:45

目录

  • 一,内存屏障
    • 1,概念
    • 2,内存屏障的效果
    • 3,cpu中的内存屏障
  • 二,JVM中提供的四类内存屏障指令
  • 三,volatile 特性
    • 1,保证内存可见性定义
    • 2,禁止指令重排序
    • 3,不保证原子性

一,内存屏障

1,概念

内存屏障是硬件之上、操作系统或JVM之下,对并发作出的最后一层支持。再向下是是硬件提供的支持;向上是操作系统或JVM对内存屏障作出的各种封装。内存屏障是一种标准,各厂商可能采用不同的实现

2,内存屏障的效果

即使指令的执行没有重排序,是按顺序执行的,但由于缓存的存在,仍然会出现数据的非一致性的情况。我们把这种普通读``普通写可以理解为是有延迟的延迟读、延迟写,因此即使读在前、写在后,因为有延迟,然后仍然会出现写在前、读在后的情况。
为了解决上述重排带来的问题,提出了as-if-serial原则,即不管怎么重排序,程序执行的结果在单线程里保持不变。为了遵守as-if-serial原则,我们需要一种特殊的指令来阻止特定的重排,使其保持结果一致,这种指令就是内存屏障。

内存屏障有两个效果:

  • 阻止指令重排序:在插入内存屏障指令后,不管前面与后面任何指令,都不能与内存屏障指令进行重排,保证前后的指令按顺序执行,即保证了顺序性。
  • 全局可见:插入的内存屏障,保证了其对内存操作的读写结果会立即写入内存,并对其他CPU核可见,即保证了可见性,解决了普通读写的延迟问题。例如,插入读屏障后,能够删除缓存,后续的读能够立刻读到内存中最新数据(至少当时看起来是最新)。插入写屏障后,能够立刻将缓存中的数据刷新入内存中,使其对其他CPU核可见。

3,cpu中的内存屏障

lfence:读屏障(load fence),即立刻让CPU Cache失效,从内存中读取数据,并装载入Cache中。
sfence: 写屏障(write fence), 即立刻进行flush,把缓存中的数据刷入内存中。
mfence: 全屏障 (memory fence),即读写屏障,保证读写都串行化,确保数据都写入内存并清除缓存。

二,JVM中提供的四类内存屏障指令

loadload:
读读
,该屏障用来禁止处理器把上面的volatile读与下面的普通读重排序
storestore:
写写
,该屏障可以保证在volatile写之前,其前面的所有普通写操作都已经刷新到主内存中
loadstore:
读写
,该屏障用来禁止处理器把上面的volatile读与下面的普通写重排序
storeload:
写读
,该屏障的作用是避免volatile与后面可能有的volatile读/写操作重排序

三,volatile 特性

1,保证内存可见性定义

(1)定义:
可见性的定义常见于各种并发场景中,以多线程为例:当一个线程修改了线程共享变量的值,其它线程能够立即得知这个修改。
从性能角度考虑,没有必要在修改后就立即同步修改的值——如果多次修改后才使用,那么只需要最后一次同步即可,在这之前的同步都是性能浪费。因此,实际的可见性定义要弱一些,只需要保证:当一个线程修改了线程共享变量的值,其它线程在使用前,能够得到最新的修改值。
(2)如何保证可见性
Java内存模型中定义的8种工作内存与主内存之间的原子操作
在这里插入图片描述

  • read: 作用于主内存,将变量的值从主内存传输到工作内存,主内存到工作内存
  • load: 作用于工作内存,将read从主内存传输的变量值放入工作内存变量副本中,即数据加载
  • use: 作用于工作内存,将工作内存变量副本的值传递给执行引擎,每当JVM遇到需要该变量的字节码指令时会执行该操作
  • assign: 作用于工作内存,将从执行引擎接收到的值赋值给工作内存变量,每当JVM遇到一个给变量赋值字节码指令时会执行该操作
  • store: 作用于工作内存,将赋值完毕的工作变量的值写回给主内存
  • write: 作用于主内存,将store传输过来的变量值赋值给主内存中的变量
    由于上述只能保证单条指令的原子性,针对多条指令的组合性原子保证,没有大面积加锁,所以,JVM提供了另外两个原子指令:
  • lock: 作用于主内存,将一个变量标记为一个线程独占的状态,只是写时候加锁,就只是锁了写变量的过程。
  • unlock: 作用于主内存,把一个处于锁定状态的变量释放,然后才能被其他线程占用

2,禁止指令重排序

(1)定义
重排序并没有严格的定义。整体上可以分为两种:
真·重排序:编译器、底层硬件(CPU等)出于“优化”的目的,按照某种规则将指令重新排序(尽管有时候看起来像乱序)。
伪·重排序:由于缓存同步顺序等问题,看起来指令被重排序了。
(2)问题来源
重排序问题无时无刻不在发生,源自三种场景:

  • 编译器编译时的优化
  • 处理器执行时的乱序优化
  • 缓存同步顺序(导致可见性问题)
    场景1、2属于真·重排序;场景3属于伪·重排序。场景3也属于可见性问题

(3)怎么禁止指令重排序

volatile有关禁止指令重排的行为
当第一个操作是 volatile 读时,不论第二个操作是什么,都不能重排序;这个操作保证了volatile读之后的操作不会被重排到volatile读之前
当第二个操作为 volatile 写时,不论第一个操作是什么,都不能重排序;这个操作保证了volatile写之前的操作不会被重排到volatile写之后
当第一个操作为 volatile 写时,第二个操作为 volatile 读时,不能重排序

3,不保证原子性

volatile变量的复合操作(如i++)是不具有原子性的,原因是 i++ 操作从字节码角度来看,是分为三步的
在这里插入图片描述
多线程环境下,数据计算和数据赋值操作可能多次出现,即操作非原子。若数据再加载之后,若主内存中 count变量发生修改之后,由于线程工作内存中的值在此之前已经加载,从而不会对变更操作做出相应变化,即私有内存和公共内存中变量不同步,进而导致数据不一致
对于volatile变量,JVM只是保证从主内存加载到线程工作内存的值是最新的,也就是数据加载时是最新的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/529002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Http与Https 比较

目录 1、HTTP(HyperText Transfer Protocol:超文本传输协议) 2、HTTPS(Hypertext Transfer Protocol Secure:超文本传输安全协议) 3、HTTP 与 HTTPS 区别 4、HTTPS 的工作原理 1、HTTP(HyperTex…

MySQL---存储过程(局部变量、用户变量、系统变量(全局变量、会话变量)、传参(in、out、inout))

1. 存储过程特性 存储过程就是数据库 SQL 语言层面的代码封装与重用。 有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现 复杂的逻辑功能; 函数的普遍特性:模块…

全球特种无人机市场规模逐渐扩大,预计今年将突破120亿美元

翱翔于空中是人们长久的追求,1903年,莱特兄弟发明了第一家螺旋桨飞机,这次飞行标志着飞机时代的开始。科技发展到今天,无人机(英文简称为“UAV”)作为一种高科技产品已经逐渐走进人们的生活中。 无人机技术…

如何解决浏览器跨域问题?

浏览器判断是跨域请求会在请求头上添加origin,表示这个请求来源哪里。比如: Plaintext GET / HTTP/1.1 Origin: http://localhost:8601服务器收到请求判断这个Origin是否允许跨域,如果允许则在响应头中说明允许该来源的跨域请求,…

【windows批处理batch】批处理batch字符串处理相关操作(字符串定义、分割、拼接、替换、切片、查找)

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、…

从万和电气看民企如何获得“新增长”

改革开放至今,中国民营企业在经过蒙眼狂奔的三十多年后,普遍迎来发展难题: 1,第一代创业者普遍进入退休年龄,面临代际传承问题; 2,民营企业尤其是偏传统行业的企业,如何在新的行业…

基于SSM的高校图书借阅管理系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

mybatis-plus基本使用流程以及进阶操作

参考 https://www.bilibili.com/video/BV1dQ4y1A75e?p7&vd_source6346698154746eb5026e16499e253fe8 使用流程 一、 准备工作 3.引入依赖 4.插件 spring-boot-starter spring-boot-starter-test mybatis-plus-boot-starter MySQL lombok:用于简化实体类的创建…

查看 PostgreSQL 中的表定义和说明

要查看 PostgreSQL 中的表定义和说明&#xff0c;您可以使用以下命令&#xff1a; 1. 查看表定义&#xff1a; \d <table_name>例如&#xff0c;要查看 pg_extension 表的定义&#xff0c;您可以运行以下命令&#xff1a; \d pg_extension2. 查看表说明&#xff1a; …

山东移动:全业务域核心系统升级,实现大幅降本增效

本文介绍了山东移动引入 OceanBase 到山东省 BOSS/CRM 核心系统领域的相关情况。欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 中国移动通信集团山东有限公司&#xff08;以下简称"山东移动"&#xff09; 隶属于中国移动通信集团公司…

【刷题之路】LeetCode 232. 用栈实现队列

【刷题之路】LeetCode 232. 用栈实现队列 一、题目描述二、解题1、图解主要思路2、先实现栈3、实现各个接口3.1、初始化接口3.2、入队接口3.3、出队接口3.4、取队头接口3.5、判空接口3.6、释放接口 一、题目描述 原题连接&#xff1a; 232. 用栈实现队列 题目描述&#xff1a;…

Babylon.js大规模场景优化实践

在本文中&#xff0c;我们将重点介绍用于优化 Babylon.js 海港场景的优化和架构技术。 我们的场景总共有超过 600 个网格和 1,000,000 个顶点。 在我们的 2018 Macbook Pro 上&#xff0c;它在 Google Chrome 中始终以 45 FPS 的速度运行。 我们发现 Firefox 约为 40 FPS&#…

公厕卫生间除臭杀菌空气净化解决方案

人每天平均大约有80%以上时间是在室内度过&#xff0c;室内空气同时面临着化学污染、物理污染和生物污染&#xff0c;据统计室内污染比室外高5~10倍&#xff0c;因此室内空气质量问题对人的伤害比室外污染更大。常见的空气污染有病毒、烟雾、甲醛、细菌、PM2.5等&#xff0c;如…

淘宝商品详情数据采集,支持高并发请求

一、如何通过手动方式查看阿里巴巴商品详情页面的数据 1.淘宝天猫商品详情 API 接口&#xff08;item_get - 获得淘宝商品详情接口&#xff09;&#xff0c;淘宝API 接口代码对接可以获取到宝贝 ID&#xff0c;宝贝标题&#xff0c;价格&#xff0c;优惠价&#xff0c;掌…

C++优化方法

C优化方法 文章目录 C优化方法1.整数运算效率高于浮点2.除法和取余4.通过2的幂次进行除法和取余数5.使用数组下标6.全局变量->局部变量7.指针值不改变的->拷贝到局部变量8.变量类型9.局部变量10.指针11.指针链12.条件执行13.布尔表达式和范围检查14.布尔表达式和零值比较…

【UE4 像素流 WEBUI插件】部署像素流

目录 一、单实例本地像素流送 步骤 1. 勾选插件 2. 打包工程并启动信令服务器 3. 创建快捷方式并启动游戏 二、单实例局域网像素流送 步骤 1. 编辑cirrus.js 2. 编辑快捷方式属性 3. 启动 三、集成WEBUI插件 一、单实例本地像素流送 步骤 1. 勾选插件 勾选使用“Pix…

数字化时代下,企业如何利用数字化提升企业竞争力?

在数字化时代的今天&#xff0c;企业越来越意识到数字化的重要性。数字化已经成为企业竞争的关键。在数字化时代下&#xff0c;企业的竞争力也已经从传统的硬实力向软实力转变。企业需要利用数字化技术来提高竞争优势&#xff0c;从而在激烈的竞争中脱颖而出。 目前&#xff0c…

Mysql_行锁、临键锁、间隙锁的理解

目录 行锁间隙锁临键锁总结 行锁 行锁&#xff0c;也称为记录锁。 当我们针对主键或者唯一索引加锁的时候&#xff0c;Mysql默认会对查询的这一行数据加行锁&#xff0c;避免其他事务对这一行数据进行修改。 间隙锁 间隙锁&#xff0c;顾名思义&#xff0c;就是锁定一个索引…

浅谈作为程序员如何写好文档:结构化写作

我作为从一名懵懂的实习生转变为工程师的工作经历中&#xff0c;伴随着技术经验的成长&#xff0c;也逐渐意识到了编写文档是知识和经验传递给其他人的最有效方式。通过文档&#xff0c;可以分享我的技术知识和最佳实践&#xff0c;使其他人更好地理解我的工作。在这里&#xf…

图解 SQL 执行顺序,清晰明了

这是一条标准的查询语句: 这是我们实际上SQL执行顺序&#xff1a; 我们先执行from,join来确定表之间的连接关系&#xff0c;得到初步的数据 where对数据进行普通的初步的筛选 group by 分组 各组分别执行having中的普通筛选或者聚合函数筛选。 然后把再根据我们要的数据进行…