持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
缓存一致性协议(MESI)
前言
随着这计算机的不断发展,到了现在咱们的计算机已经是多核、多cpu的了。
CPU如果需要对某个数据进行更新的话,需要将主存中的数据读取到对应CPU的缓存,再由CPU来进行相应的更新操作。
多CPU引发的问题
假如多个CPU都看上了主存中的同一个数据,它们都想更新该数据怎么办?
这种问题就像是在并发环境下,读者和写者的问题类似。
如何保证数据一致性?
既然是和读者写者很是相似,那么我们自然而然就可以想到了——加锁
给总线加锁
比如说CPU1已经将主存中的一个数据读取到了CPU1缓存了,那这时候,会在bus总线上释放一个lock的信息,禁止其他线程来访问,直到锁释放。
这种方法是由硬件实现的,而且是直接加锁,会在很大程度上降低性能(本来多CPU的出现就是为了提高性能的)。
缓存一致性协议
为了在不加bus锁且维护缓存一致性,提出了缓存一致性协议。
既然加锁太麻烦了,那就相互多点信任,大家通过协议协商。
直接给总线加锁是会锁住所有数据的,所以在缓存一致性协议中提出了缓存行的概念。
缓存行: 其实可以理解为从主存读取到CPU缓存的数据块。
在缓存一致性协议中为缓存行设置了以下几种状态:
- M - 被修改
- E - 独享
- S - 共享
- I - 无效
比如:
- 主存中的x变量首先被读取到了CPU1缓存中,此时在CPU1缓存的状态就应该是 E;注意这时候会启动操作系统的嗅探功能,CPU1可以感知到后来谁想读取变量x的。
- 当CPU2也来读取变量x的时候,CPU1感知到了,就将状态从 E 转变为 S;与此同时,CPU2中的状态也就也是 S。
- 假设这时候CPU1将变量x的值改变了,那么这时候CPU1的缓存行状态就变成 M 了,而CPU2那边状态就变成了 I
- 当CPU1将变量x的新值写回主存的时候,状态就变回了 S,同样的,CPU2再次从主存中读取x的新值,状态变为 S(先前的状态是 I ,失效了),