缓存一致性协议(MESI)

148 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情

缓存一致性协议(MESI)

前言

随着这计算机的不断发展,到了现在咱们的计算机已经是多核、多cpu的了。

CPU如果需要对某个数据进行更新的话,需要将主存中的数据读取到对应CPU的缓存,再由CPU来进行相应的更新操作。

image.png

多CPU引发的问题

假如多个CPU都看上了主存中的同一个数据,它们都想更新该数据怎么办?

这种问题就像是在并发环境下,读者和写者的问题类似。

如何保证数据一致性?

既然是和读者写者很是相似,那么我们自然而然就可以想到了——加锁

给总线加锁

image.png

比如说CPU1已经将主存中的一个数据读取到了CPU1缓存了,那这时候,会在bus总线上释放一个lock的信息,禁止其他线程来访问,直到锁释放。

这种方法是由硬件实现的,而且是直接加锁,会在很大程度上降低性能(本来多CPU的出现就是为了提高性能的)。

缓存一致性协议

为了在不加bus锁且维护缓存一致性,提出了缓存一致性协议。

既然加锁太麻烦了,那就相互多点信任,大家通过协议协商。

image.png

直接给总线加锁是会锁住所有数据的,所以在缓存一致性协议中提出了缓存行的概念。

缓存行: 其实可以理解为从主存读取到CPU缓存的数据块。

在缓存一致性协议中为缓存行设置了以下几种状态:

  1. M - 被修改
  2. E - 独享
  3. S - 共享
  4. I - 无效

比如:

  1. 主存中的x变量首先被读取到了CPU1缓存中,此时在CPU1缓存的状态就应该是 E;注意这时候会启动操作系统的嗅探功能,CPU1可以感知到后来谁想读取变量x的。
  2. 当CPU2也来读取变量x的时候,CPU1感知到了,就将状态从 E 转变为 S;与此同时,CPU2中的状态也就也是 S。
  3. 假设这时候CPU1将变量x的值改变了,那么这时候CPU1的缓存行状态就变成 M 了,而CPU2那边状态就变成了 I
  4. 当CPU1将变量x的新值写回主存的时候,状态就变回了 S,同样的,CPU2再次从主存中读取x的新值,状态变为 S(先前的状态是 I ,失效了),