内存模型如何解决缓存一致性问题

本文介绍了缓存一致性问题及其解决方案,重点讲解了MESI协议的工作原理,如何保证多核CPU中缓存数据的一致性。同时,区分了缓存一致性与内存一致性,指出内存一致性确保多线程环境下程序访问内存的正确性。MESI协议虽能保证一致性但不保证实时性,而内存模型则涉及编程语言、编译器和CPU间的协议,确保并发编程的原子性、有序性和可见性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看:

    Java内存模型介绍_向前走-优快云博客

通过上面的文章,我们了解了缓存一致性问题,并且知道了结果:引入计算机内存模型可以解决这个问题。

那么,内存模型到底是怎么保证缓存一致性的呢?

首先,缓存一致性是由于引入缓存而导致的问题,所以,这是很多CPU厂商必须解决的问题。为了解决前面提到的缓存数据不一致的问题,人们提出过很多方案,通常来说有以下2种方案:

  • 1、通过在总线加LOCK#锁的方式。

  • 2、通过缓存一致性协议(Cache Coherence Protocol)。

    在早期的CPU当中,是通过在总线上加LOCK#锁的形式来解决缓存不一致的问题。因为CPU和其他部件进行通信都是通过总线来进行的,如果对总线加LOCK#锁的话,也就是说阻塞了其他CPU对其他部件访问(如内存),从而使得只能有一个CPU能使用这个变量的内存。在总线上发出了LCOK#锁的信号,那么只有等待这段代码完全执行完毕之后,其他CPU才能从其内存读取变量,然后进行相应的操作。这样就解决了缓存不一致的问题。

但是由于在锁住总线期间,其他CPU无法访问内存,会导致效率低下。因此出现了第二种解决方案,通过缓存一致性协议来解决缓存一致性问题。

缓存一致性协议

    缓存一致性协议(Cache Coherence Protocol),最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。

    MESI的核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取

     在MESI协议中,每个缓存可能有有4个状态,它们分别是:

M(Modified):这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。
E(Exclusive):这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中。
S(Shared):这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中。
I(Invalid):这行数据无效。

     只要知道,MESI是一种比较常用的缓存一致性协议,他可以用来解决缓存之间的数据一致性问题就可以了。

    但是,值得注意的是,传统的MESI协议中有两个行为的执行成本比较大。

  • 一个是将某个Cache Line标记为Invalid状态;
  • 另一个是当某Cache Line当前状态为Invalid时写入新的数据。

    所以CPU通过Store Buffer和Invalidate Queue组件来降低这类操作的延时。

        如图:

我重新整理原文表述

        当一个CPU进行写入时,首先会给其它CPU发送Invalid消息,然后把当前写入的数据写入到Store Buffer中。然后异步在某个时刻真正的写入到Cache中。

                所以如果当前CPU核要读Cache中的数据时,需要先扫描Store Buffer之后再读取Cache。

        但是此时其它CPU核是看不到当前核的Store Buffer中的数据的,要等到当前核Store Buffer中的数据被刷到了当前核的Cache之后,其它CPU核的Cache才会触发失效操作。

                所以当其它CPU核收到Invalid消息时,会把消息写入自身的Invalidate Queue中,随后异步将其设为Invalid状态。

        和Store Buffer不同的是,当前CPU核要读Cache中的数据时,需要先扫描Store Buffer之后再读取Cache,但是当前CPU核心使用Cache时并不会扫描Invalidate Queue部分,所以可能会有极短时间的脏读问题(可能读了数据之后,该数据会被置为无效状态)。

总结:

    所以,为了解决缓存的一致性问题,比较典型的方案是MESI缓存一致性协议。

    但是虽然MESI协议,可以保证缓存的一致性,但是无法保证实时性

 

内存模型

    内存模型(Memory Model)如果扩展开来说的话,通常指的是内存一致性模型(Memory Sequential Consistency Model)

前面我们提到过缓存一致性,这里又要说内存一致性,希望通过对比更加清楚。

  • 缓存一致性(Cache Coherence),解决是多个缓存副本之间的数据的一致性问题。

  • 内存一致性(Memory Consistency),保证的是多线程程序访问内存时可以读到什么值。

    如果没有Memory Consistency,程序员写的程序代码的输出结果是不确定的。

    因此,Memory Consistency就是程序员(编程语言)、编译器、CPU间的一种协议。这个协议保证了程序访问内存时会得到什么值。

    简单点说,内存一致性,就是保证并发场景下的程序运行结果和程序员预期是一样的(当然,要通过加锁等方式),包括的就是并发编程中的原子性、有序性和可见性。而缓存一致性说的就是并发编程中的可见性

    在很多内存模型的实现中,关于缓存一致性的保证都是通过硬件层面缓存一致性协议来保证的。需要注意的是,这里提到的内存模型,是计算机内存模型,而非Java内存模型。

总结

     缓存一致性问题。硬件层面的问题,指的是由于多核计算机中有多套缓存,各个缓存之间的数据不一致性问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值