前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >内存屏障保证缓存一致性优化

内存屏障保证缓存一致性优化

作者头像
用户1174983
发布于 2018-02-05 07:41:07
发布于 2018-02-05 07:41:07
1.6K00
代码可运行
举报
文章被收录于专栏:钟绍威的专栏钟绍威的专栏
运行总次数:0
代码可运行

 在前面内存系统重排序提到,“写缓存没有及时刷新到内存,导致不同处理器缓存的值不一样”,出现这种情况是糟糕的,所幸处理器遵循缓存一致性协议能够保证足够的可见性又不过多的损失性能。

 缓存一致性协议给缓存行(通常为64字节)定义了个状态:独占(exclusive)、共享(share)、修改(modified)、失效(invalid),用来描述该缓存行是否被多处理器共享、是否修改。所以缓存一致性协议也称MESI协议

  • 独占(exclusive):仅当前处理器拥有该缓存行,并且没有修改过,是最新的值。
  • 共享(share):有多个处理器拥有该缓存行,每个处理器都没有修改过缓存,是最新的值。
  • 修改(modified):缓存行被修改过了,需要写回主存,并通知其他拥有者 “该缓存已失效”。
  • 失效(invalid):缓存行被其他处理器修改过,该值不是最新的值,需要读取主存上最新的值。

优化

 处理修改状态是比较耗时的操作,既要发送失效消息给其他拥有者并写回主存,还要等待其他拥有者处理失效信息,直到收到失效消息的响应。如果在这一段时间,处理器都处于空等,那是奢侈的。所以引入缓存失效缓存来让处理器不再“等”。

存储缓存

 存储缓存(Store Buffers),也就是常说的写缓存,当处理器修改缓存时,把新值放到存储缓存中,处理器就可以去干别的事了,把剩下的事交给存储缓存。

失效队列

 处理失效的缓存也不是简单的,需要读取主存。并且存储缓存也不是无限大的,那么当存储缓存满的时候,处理器还是要等待失效响应的。为了解决上面两个问题,引进了失效队列(invalidate queue0)。

 处理失效的工作如下:

  1. 收到失效消息时,放到失效队列中去。
  2. 为了不让处理器久等失效响应,收到失效消息需要马上回复失效响应。
  3. 为了不频繁阻塞处理器,不会马上读主存以及设置缓存为invlid,合适的时候再一块处理失效队列。

引发内存重排序

 下面是处理器A、B,依次写、读内存a的时序图。A、B都缓存了a。

 可以看到即使遵守缓存一致性协议,也会有一段时间缓存不一致(①-⑥)。

 要是读取a的操作在这段时间内,那么处理器B看到的a将是0。处理器执行顺序为写a>读a,而在内存上的顺序为读a>写a,造成了重排序重排序可能会导致不可见性,要是此时线程A、B分别在处理器A、B上执行,那么线程A执行了写操作后,线程B看不到线程A执行的结果,共享内存a不可见,改变了程序运行结果。

避免内存重排序

 引发重排序是糟糕的,可能造成共享内存不可见,改变程序结果。那么该怎么办,不进行MESI优化吗?既不能追求性能,造成重排序,也不能追求可见性(非共享数据可见是不需要的),降低性能。

 处理器还是使用提供了个武器——内存屏障指令(Memory Barrier):

  1. 写内存屏障(Store Memory Barrier):处理器将当前存储缓存的值写回主存,以阻塞的方式。
  2. 读内存屏障(Load Memory Barrier):处理器处理失效队列,以阻塞的方式。

 可以看到内存屏障可以阻止内存系统重排序,保证可见性。但其开销也很大,处理器需要阻塞等待,一般应用在锁的获取和释放中。

上面那段处理器A、B,依次写、读内存a,加了内存屏障后,就不会被重排序了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
boolean finish = false;
int a = 0;

//处理器A:
a = 1;
storeMemoryBarrer(); //保证a一定在主存中,且处理器B中a为invlid
finish = true;

//处理器B:
while(!finish);
loadMemoryBarrier(); //保证缓存到a最新的值,执行后a为share
assert a == 1;

JMM中抽象内存屏障

 为了更好的理解如何实现同步的可见性,JMM抽象出了内存屏障Memory Barrier。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-12-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
缓存一致性与内存屏障
摩尔定律告诉我们:大约每18个月会将芯片的性能提高一倍。芯片的这种飞速发展直接导致了芯片的指令执行速度与内存读取速度之间的巨大鸿沟。
蝉沐风
2022/07/27
9630
缓存一致性与内存屏障
聊聊内存屏障_内存栅栏
在之前文章聊聊JMM,说到了内存屏障,内存屏障在Java语言实现一致性内存模型上起到了重要的作用,本文我们一起聊一聊内存屏障
全栈程序员站长
2022/09/20
9380
聊聊内存屏障_内存栅栏
CPU缓存和内存屏障
为了提高程序的运行性能, 现代CPU在很多方面对程序进行了优化 例如: CPU高速缓存, 尽可能的避免处理器访问主内存的时间开销, 处理器大多会利用缓存以提高性能
CodingDiray
2019/09/25
2.7K0
CPU缓存和内存屏障
【深度长文】学好并发编程不一定需要了解的MESI和内存屏障
synchronize保证了原子性、可见性。(如果撇开DCL问题的话,所有变量都在同步代码块内处理的话,甚至也可以说保证了不同同步代码块之间的有序性) ReentrantLock等保证原子性、可见性、有序性 volatile保证了可见性、有序性
RRT冻羊
2022/11/03
7100
【深度长文】学好并发编程不一定需要了解的MESI和内存屏障
Java高并发:Java内存模型
因为缓存脏数据写回主内存一般采用的是写回法,而非直写法,所以缓存和主存之间会有数据一致性问题。
冰寒火
2023/03/01
8490
CPU缓存一致性:从理论到实战
速度快的存储硬件成本高、容量小,速度慢的成本低、容量大。为了权衡成本和速度,计算机存储分了很多层次,扬长避短,有寄存器、L1 cache、L2 cache、L3 cache、主存(内存)和硬盘等。图1 展示了现代存储体系结构。
刘盼
2023/10/27
1.3K0
CPU缓存一致性:从理论到实战
解密Linux内核神器:内存屏障的秘密功效与应用方法
现在大多数现代计算机为了提高性能而采取乱序执行,这可能会导致程序运行不符合我们预期,内存屏障就是一类同步屏障指令,是CPU或者编译器在对内存随机访问的操作中的一个同步点,只有在此点之前的所有读写操作都执行后才可以执行此点之后的操作。
嵌入式Linux内核
2023/06/28
1K0
解密Linux内核神器:内存屏障的秘密功效与应用方法
CPU高速缓存与内存屏障
最后,关于写作内存相关的原因是为了更好地理解同步关键字synchronized的内存语义(下一篇哈)
keithl
2020/03/10
1.8K0
CPU高速缓存与内存屏障
JAVA线程-CPU缓存和内存屏障(四)
1.修改态(Modified),此cache行已被修改过(脏行),内容已不同于主存,为此cache专有。 2.专有态(Exclusive),此cache行内容同于主存,但不出现于其他cache中。 3.共享态(Shared),此cache行内容同于主存,但也出现于其他cache中。 4.无效态(Invalid),此cache行内容无效,需要从主内存重新加载。
IT架构圈
2020/03/28
1.9K0
voliate关键字原理
被volatile修饰的变量在编译成字节码文件时会多个lock指令,该指令在执行过程中会生成相应的内存屏障,以此来解决可见性跟重排序的问题。
全栈程序员站长
2022/08/15
6510
voliate关键字原理
基础篇:深入JMM内存模型解析volatile、synchronized的内存语义
特殊的是StoreLoad,会使该屏障之前的所有内存访问指令(装载和存储指令)完成之后,才执行该屏障之后的内存访问指令;是一个”全能型”的屏障,它同时具有其他三个屏障的效果
潜行前行
2020/12/11
6600
基础篇:深入JMM内存模型解析volatile、synchronized的内存语义
C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI
然后看看标准C++基金会(https://isocpp.org)怎么说的(官方链接):
一见
2019/03/14
3.7K0
C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI
谈谈volatile
volatile通常被比喻成“轻量级的synchronized”,也是Java并发编程中比较重要的一个关键字。和synchronized不同,volatile是一个变量修饰符,只能用来修饰变量,无法修饰方法或代码块等。
Java阿呆
2020/10/26
4710
谈谈volatile
面试官:说说volatile底层实现原理?
在 Java 并发编程中,有 3 个最常用的关键字:synchronized、ReentrantLock 和 volatile。
磊哥
2024/02/29
1550
Intel DPDK的内存屏障介绍
了解更多欢迎访问知乎 :https://www.zhihu.com/people/mu-mu-67-87-35
通信行业搬砖工
2023/12/21
3640
Intel DPDK的内存屏障介绍
99%的人没弄懂volatile的设计原理,更别说灵活运用了
写volatile的文章非常多,本人也看过许多相关文章,但始终感觉有哪里不太明白,但又说不上来说为什么。可能是过于追求底层实现原理,老想问一个为什么吧。
程序新视界
2021/12/07
4180
99%的人没弄懂volatile的设计原理,更别说灵活运用了
2.2 指令重排&happens-before 原则 & 内存屏障
令重排序:java语言规范规定JVM线程内部维持顺序化语义。即只要程序的最终结果 与它顺序化情况的结果相等,那么指令的执行顺序可以与代码顺序不一致,此过程叫指令的 重排序。
用户7798898
2020/09/27
2K0
2.2 指令重排&happens-before 原则 & 内存屏障
【云+社区年度征文】深入理解Volatile关键字和使用
背景:计算机在执行程序时,每条指令都是由CPU调度执行的。CPU执行计算指令时,产生与内存(物理内存)通讯的过程(即数据的读取和写入),由于CPU执行速度很快,而从内存读取数据和内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存(Cache)。
沁溪源
2020/12/19
3260
【云+社区年度征文】深入理解Volatile关键字和使用
【Java线程】深入理解Volatile关键字和使用
理解volatile底层原理之前,首先介绍关于缓存一致性协议的知识。 背景:计算机在执行程序时,每条指令都是由CPU调度执行的。CPU执行计算指令时,产生与内存(物理内存)通讯的过程(即数据的读取和写入),由于CPU执行速度很快,而从内存读取数据和内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存(Cache)。
沁溪源
2020/12/22
4290
【Java线程】深入理解Volatile关键字和使用
浅墨: 聊聊原子变量、锁、内存屏障那点事(2)
编译器优化乱序和CPU执行乱序的问题可以分别使用优化屏障 (Optimization Barrier)和内存屏障 (Memory Barrier)这两个机制来解决:
Linux阅码场
2019/10/08
1.7K0
浅墨: 聊聊原子变量、锁、内存屏障那点事(2)
推荐阅读
相关推荐
缓存一致性与内存屏障
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文