JAVA并发编程之原子性、可见性与有序性

并发编程-原子性、可见性与有序性

一、CPU的可见性

1.1 缓存一致性问题的出现

CPU处理器在处理速度上,远胜于内存,主内存执行一次内存的读写操作,所需要的时间足够处理器去处理上百条指令。

为了弥补处理器与主内存处理能力之间的差距,CPU引入了高级缓存。CPU去主内存拉取数据后,会将数据存储到CPU的高级缓存中,下次如果还涉及到操作这个数据,直接从CPU高速缓存中获取即可,避免了长时间的和主内存操作,对CPU带来的性能损耗。

随着硬件能力不断的提升,现在的CPU都是多核的,而每个CPU内核都有自己的高速缓存。如果主内存中的同一个数据,被多个CPU内核缓存了,如果其中一个内核修改了数据,另一个内核不知道!造成了数据的不一致性。

1.2 CPU的高速缓存模型

image.png

1.3 CPU缓存行

数据在高速缓存中不是以独立项来存储的,他的数据都存储在缓存行中,CacheLine。缓存行是CPU高速缓存的最小存储单位。

目前主流的CPU缓存的缓存行通常是64字节。

比如剖析开高速缓存,里面就是多个缓存行组成滴。

image.png

比如Java中一个long类型是8字节,一个缓存行最多就可以缓存8个Long类型数据。

1.4 MESI协议

并不是所有的CPU都基于MESI协议去制作CPU,但是主流的CPU大多都是基于MESI协议来解决缓存一致性问题的。

M:modify修改了

表示缓存行数据被修改了,并且没有同步到主内存。而且这个数据是当前CPU独占的,其他CPU内核的缓存没有这个数据。

这个状态数据没有安全问题。

E:exclusive独占

表示缓存行数据是独占的,并且这个数据没有被修改,和主内存的数据是一致的。

这个状态数据没有安全问题。

S:shared共享

表示缓存行数据是共享的,这个数据被多个CPU缓存在缓存行中。并且都与内存中的值是一致的。

这个状态数据没有安全问题。

I:invalid无效

表示缓存行的数据是无效的,如果需要使用这个数据,需要重新去主内存拉取(那边同步完)。

1.5 MESI是如何保证缓存一致性

MESI协议对不同的状态增加了不同的 监听任务

  • 一个处于M状态的缓存行,必须时刻监听所有试图读取当前缓存行对应的主内存数据地址的操作。如果坚挺到有其他内核要读取这个数据,必须在读取操作之前先将缓存行数据写回主内存。
  • 一个处于S状态的缓存行,必须时刻监听该缓存行 无效 或者 独占 或者 修改 当前缓存行的请求,如果监听到,将当前缓存行状态设置为I。
  • 一个处于E状态的缓存行,必须时刻监听视图 读取 当前缓存行对应的主内存地址的操作,如果监听到,将当前缓存行状态修改为S。

核心其实在于第一点和第二点。

第一点:可以避免其他线程读取到主内存的脏数据。

第二点:可以将缓存不一致的情况的缓存行设值为无效。

1.6 CPU写优化层面对MESI协议的影响

写缓冲器(StoreBuffer,WriteBuffer)是处理器内部一个容量比L1还笑的一个高速缓存组件,每个CPU内核都有自己的Store Buffer。一些写操作,不会直接执行落到L1缓存上,而是先落到StoreBuffer上,这样CPU可以省去等待响应的时间,减少写操作的延迟,提升CPU的效率。但是这种情况会影响到MESI协议的触发,导致其他缓存行应当变为I状态,但是因为StoreBuffer数据还没落到L1,导致无法触发。

无效化队列(Invalidate Queue),这个东西是处理Invalidate消息的。这个Queue是做优化滴,需要将invalid处理广播给其他的CPU,并且其他CPU需要返回一个response,大量的广播消息需要一定时间的等待response。CPU在做广播时,会将invalid消息扔到无效化队列中,不需要直接响应response消息了,减少了写操作消耗的时间。

上述两种对CPU写操作的优化,会导致MESI协议触发存在延迟甚至无法触发的问题。在CPU层面为了解决这个问题,就需要一个指令,那就是lock指令。

lock前缀指令 期间的写操作,会立即写回主内存,那CPU的高速缓存必然也要写回去,必然会触发MESI协议,让其他缓存行将状态同步。

二、CPU的原子性

CPU的一条指令必然是原子性的。

但是一些其他程序的操作,到了咱们CPU执行层面上,可能会有多个指令。就比如i++,在CPU层面是三条指令:

  • 主内存读取数据
  • 寄存器+1
  • 数据写回主内存

但是对于修改数据而言,还是会因为多核CPU并行处理,导致一些数据安全问题,所以CPU也需要保证原子性的一些操作。就比如CAS指令,这个是CPU支持的原语。

but,CPU支持一个指令叫做cmpxchg,也就是CAS操作,在多核情况下,如果没有保证多核之间的原子性,会导致cmpxchg操作,存在数据安全问题。

So,在多核CPU下,执行cmpxchg指令时,会在前面甩一个lock指令,来保证多核CPU的原子性。

lock指令类似CPU中的锁操作,并且锁操作的粒度有两种。

  • 总线锁:会锁总线,其他所有CPU内核对主内存做读写操作请求时,都会被阻塞住,直到释放总线锁。
  • 缓存锁:因为总线锁效率嘎嘎低,现在的CPU都是采用锁缓存提来锁总线。在没有办法利用缓存所时,会被迫使用总线锁。

Lock前缀指令 在Intel官方的一些文档信息:https://www.felixcloutier.com/x86/lock

三、CPU的有序性

首先要请求,CPU本身会在一定规则下,对一些指令进行重新排序。

比如as-if-serial原则,保证单线程的程序结果不变的情况下,随便重排序。重新排序的目的是为了提升CPU的执行效率,合理的利用CPU的等待时间。

在多核CPU的情况下,因为多核CPU上的指令存在同时指定的情况,如果涉及到临界资源的修改,这种指令重排序会影响多线程运行结果的准确性。

内存屏障(Memory Barrier/Memory fence)是硬件层面提供的一些列的特殊指令,当CPU处理到这些指令时,会做一些特殊的处理,来规避重排序带来的问题。

在×86平台提供了几种比较主要的内存屏障:

  • lfence - 加载屏障
    • 放在读指令之前,阻塞屏障前后的指令重排
  • sfence - 存储屏障
    • 放在写指令之前,阻塞屏障前后的指令重排
  • mfence - 全能屏障
    • 具备了lfence和sfence的两个功能。

https://gee.cs.oswego.edu/dl/jmm/cookbook.html

image.png

mfence最终依然是 lock前缀指令

image.png

四、JMM-Java内存模型

JMM(Java Memory Model)Java内存模型是一个语言级别的内存模型抽象,他屏蔽了底层硬件实现内存一致性需求的差异,提供了对上层的统一的接口来保证内存一致性的编程能力。

Java作为一个跨平台的语言,Java内存模型就是一个中间层模式。他适配不同的底层硬件系统,设计中间层模型来做屏蔽。

任意语言编写出来而定程序,最终都会转换为机器指令,按照一定的顺序去执行,所以在语言层面来讲,都是基于硬件层面提供的一致性模型的基础上,来实现自身语言的功能和特性。

经过前面对CPU的分析:

  • Java利用汇编的CAS + lock前缀指令来实现原子性。(synchronized,ReentrantLock)
  • Java利用lock前缀指令 + MESI协议来实现的可见性。(volatile)
  • Java基于内存屏障转换为lock前缀指令来实现有序性。(volatile)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023 re:Invent 用 PartyRock 10 分钟构建你的 AI 应用

前言 一年一度的亚马逊云科技的 re:Invent 可谓是全球云计算、科技圈的狂欢,每次都能带来一些最前沿的方向标,这次也不例外。在看完一些 keynote 和介绍之后,我也去亲自体验了一些最近发布的内容。其中让我感受最深刻的无疑是 PartyRock 了。…

3 Nacos源码下载并集成达梦数据库驱动

1、Nacos源码下载 源码直接下载gitee上的nacos2.2.3,具体链接:Nacos: 概览 欢迎来到 Nacos 的世界! Nacos 致力于帮助您发现、配置和管理微服务 - Gitee.com,具体如下图

在编老师可以有副业吗

许多在编老师或许都会面临这样一个问题:除了教书育人,我是否还能有点别的追求?副业,对于很多人来说是一个增加收入、拓展兴趣的途径,但对于在编老师而言,这个问题却显得有些复杂。 老师这份工作本身就充满…

宋仕强介绍说,萨科微slkor

宋仕强介绍说,萨科微slkor(www.slkoric.com)研制了碳化硅SiC SBD二极管、碳化硅SiC MOSFET管、IGBT管、超快恢复功率二极管等高端产品,萨科微SLKOR还有肖特基二极管、ESD静电保护二极管、TVS瞬态抑制二极管、通用二极管和三极管&a…

0-前置知识

前言 SpringBoot框架在设计之初,为了有更好的兼容性,在不同的运行阶,段提供了非常多的扩展点,可以让程序员根据自己的需求,在整个Spring应用程序运行过程中执行程序员自定义的代码。 ApplicationContextInitializer …

springcloud-网关(gateway)

springcloud-网关(gateway) 概述 \Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API,并为其提供跨领域的关注,如:安全、监控/指标和容错 常用术语 Route(路由): 网关的基本构件。它由一个ID、一个目的地…

软考 系统分析师系列知识点之企业信息化规划(1)

所属章节: 第7章. 企业信息化战略与实施 第2节. 企业信息化规划 企业信息化建设是一项长期而艰巨的任务,不可能在短时间内完成。因此,企业信息化建设必然会分解成各个相对独立的项目,在不同时期分别实施,从而建立多个…

1902_野火FreeRTOS教程内核在STM32中用到的2个中断PENDSV和SYSTICK

1902_野火FreeRTOS教程内核在STM32中用到的2个中断PENDSV和SYSTICK 全部学习汇总: g_FreeRTOS: FreeRTOS学习笔记 (gitee.com) 上面是涉及到的源代码,而这次需要分析的就是78、79行的两个中断。首先,需要确认NVIC_SYSPRI2寄存器的作用。 进一…

jquery写组件滑动人机验证组件

jquery组件,虽然 jquery 语法古老,但是写好了用起来真的很爽啊,本文用滑动人机验证给大家做个详细教程(直接复制代码就可以用噢o(* ̄▽ ̄*)ブ) 第一步 先看下组件本身 component.js (function() {…

QT中的多线程有什么作用?

概述 在学习QT线程的时候我们首先要知道的是QT的主线程,也叫GUI线程,意如其名,也就是我们程序的最主要的一个线程,主要负责初始化界面并监听事件循环,并根据事件处理做出界面上的反馈。但是当我们只限于在一个主线程上…

Python urllib模块学习

HTTP协议 HTTP 协议:一般指HTTP(超文本传输)协议。 HTTP是为Web浏览器和Web服务器之间的通信而设计的,基于TCP/IP通信协议嘞传递数据。 HTTP消息结构 客户端请求消息 客户端发送一个HTTP请求到服务器的请求消息包括以下格式 请求行(request line)请求…

基于Java开发的个人视频网站的搭建与实现[附源码]

基于Java开发的个人视频网站的搭建与实现[附源码] 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系统 &am…

威来国际教育:留学服务的全新标杆,打造无忧留学体验

在当今全球化日益加深的背景下,留学已成为众多年轻人拓宽视野、提升个人能力的重要手段。随着留学市场的不断扩大和留学目的地的多样化,家庭和学生在选择留学服务时更加注重专业性和全面性。 在这一领域,威来国际教育凭借其深厚的背景和专业的…

mysql 2-20

TEXT类型 枚举类型 SET类型 二进制字符串类型 BLOB类型 注意事项 JSON类型 提取数据 空间类型 选择建议 约束

Spark 离线开发框架设计与实现

一、背景 随着 Spark 以及其社区的不断发展,Spark 本身技术也在不断成熟,Spark 在技术架构和性能上的优势越来越明显,目前大多数公司在大数据处理中都倾向使用 Spark。Spark 支持多种语言的开发,如 Scala、Java、Sql、Python 等。…

创业者看到这3000多箱磁吸春联滞销面临销毁一定要吸取教训!

2月18日,浙江金华一个工厂🏭3000多箱龙年磁吸春联, 因为滞销,加上春联中含有龙元素和日期而面临报废销毁, 造成了数十万的损失以及大量的资源浪费。 —————————— 而引起广泛的社会讨论🗣️&…

《Solidity 简易速速上手小册》第8章:高级 Solidity 概念(2024 最新版)

文章目录 8.1 高级数据类型和结构8.1.1 基础知识解析更深入的理解实际操作技巧 8.1.2 重点案例:构建一个去中心化身份系统案例 Demo:创建去中心化身份系统案例代码DecentralizedIdentityContract.sol 测试和验证拓展案例 8.1.3 拓展案例 1:管…

C++力扣题目 121--买卖股票的最佳时机 122-- 买卖股票的最佳时机II 123--买卖股票的最佳时机III 188--买卖股票的最佳时机IV

121. 买卖股票的最佳时机 力扣题目链接(opens new window) 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所…

基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 数据导入到matlab显示图像 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer:…

阿里云国际-在阿里云服务器上快速搭建幻兽帕鲁多人服务器

幻兽帕鲁是最近流行的新型生存游戏。该游戏一夜之间变得极为流行,同时在线玩家数量达到了200万。然而,幻兽帕鲁的服务器难以应对大量玩家的压力。为解决这一问题,幻兽帕鲁允许玩家建立专用服务器,其提供以下优势: &am…