CPU的缓存一致性一些与Volatile

CPU的缓存一致性一些与Volatile,第1张

CPU的缓存一致性一些与Volatile

我们都知道CPU有三级缓存,L1,L2,为核心独享,L3为CPU共享,而当前主流的CPU还都支持Store Buffer 和invalid queue,在这种情况下MESI是无法生效的,而在一些指令重排的情况下,核心读到的值可能不是最新的,这时就需要通过指令重排来进行同步,指令重排不止具备禁止重排序的特性,还具备同步刷新的特性

storebuffer和invalidate queue的设计是为了加速CPU的内存访问而设计的,但是在某些指令重排的情况下,可能会导致数据不一致的问题,所以新增了内存屏障的指令,也就是说内存屏障是为storebuffer和invalidatequeue 而设计的,目的是解决指令重排序情况下的不一致问题

volatile是JVM的内存语义,这里借用知乎中的一个回答:

volatile是java语言层面给出的保证,MSEI协议是多核cpu保证cache一致性的一种方法,中间隔的还很远,我们可以先来做几个假设:

  1. 回到远古时候,那个时候cpu只有单核,或者是多核但是保证sequence consistency,当然也无所谓有没有MESI协议了。那这个时候,我们需要java语言层面的volatile的支持吗?
当然是需要的,因为在语言层面编译器和虚拟机为了做性能优化,可能会存在 指令重排的可能,而volatile给我们提供了一种能力,我们可以告诉编译器,什么可以重排,什么不可以。
  1. 那好,假设更进一步,假设java语言层面不会对指令做任何的优化重排,那在多核cpu的场景下,我们还需要volatile关键字吗?
答案仍然是需要的。因为 MESI只是保证了多核cpu的独占cache之间的一致性,但是cpu的并不是直接把数据写入L1 cache的,中间还可能有store buffer。有些arm和power架构的cpu还可能有load buffer或者invalid queue等等。因此,有MESI协议远远不够。
  1. 再接着,让我们再做一个更大胆的假设。假设cpu中这类store buffer/invalid queue等等都不存在了,cpu是数据是直接写入cache的,读取也是直接从cache读的,那还需要volatile关键字吗?
你猜的没错,还需要的。原因就在这个“一致性”上。consistency和coherence都可以被翻译为一致性, 但是MSEI协议这里保证的仅仅coherence而不是consistency。那consistency和cohence有什么区别呢?

下面取自wiki的一段话: Coherence deals with maintaining a global order in which writes to a single location or single variable are seen by all processors. Consistency deals with the ordering of operations to multiple locations with respect to all processors.

因此,MESI协议最多只是保证了对于一个变量,在多个核上的读写顺序,对于多个变量而言是没有任何保证的。很遗憾,还是需要volatile~~

  1. 好的,到了现在这步,我们再来做最后一个假设,假设cpu写cache都是按照指令顺序fifo写的,那现在可以抛弃volatile了吧?你觉得呢?
那肯定不行啊!因为对于arm和power这个weak consistency的架构的cpu来说,它们只会保证指令之间有比如控制依赖,数据依赖,地址依赖等等依赖关系的指令间提交的先后顺序,而对于完全没有依赖关系的指令,比如x=1;y=2,它们是不会保证执行提交的顺序的,除非你使用了volatile,java把volatile编译成arm和power能够识别的barrier指令,这个时候才是按顺序的。

最后总结,答案就是:还需要~~

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5697066.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存