缓存一致性与 MESI
[← CPU Cache](CPU Cache.md)| ← 存储器导航 | ← 计算机组成原理知识地图 | ← 主页
为什么会有缓存一致性问题
单核时,Cache 主要解决“读得快不快”;多核时,还要解决“会不会读错”。
因为:
- L1、L2 往往是每个核心独有
- 同一份数据可能同时出现在多个核心的 Cache 里
- 一个核心改了数据,其他核心可能还拿着旧副本
这就是缓存一致性问题。
先记两种写策略
写直达
写 Cache 的同时,立刻写回内存。
- 优点:实现简单,一致性更容易保证
- 缺点:每次写都碰内存,性能差
写回
先只改 Cache,等这条 Cache Line 将来被替换时再写回内存。
- 优点:写得快
- 缺点:Cache 和内存可能暂时不一致,所以必须配合一致性协议
通常可以先记成:写直达 更简单,写回 性能更好,所以现代 CPU 更常围绕写回解决一致性。
保证一致性要满足什么
要真正保证一致性,至少要同时满足两件事:
- 写传播:一个核心改了数据,其他核心必须知道
- 事务串行化:多个核心改同一份数据时,必须有确定先后顺序
总线嗅探在干什么
常见方法是总线嗅探:
- 某个核心修改了数据
- 它把这个事件广播出去
- 其他核心监听总线
- 如果自己也缓存了同一份数据,就更新状态或让副本失效
它解决的是“别人知不知道我改了数据”。
MESI 四状态
MESI 本质上是一个 Cache Line 状态机,每条 Cache Line 都带一个状态:
M = Modified:已修改,和内存不一致E = Exclusive:独占,只有当前核心有,且和内存一致S = Shared:共享,多个核心都有,且和内存一致I = Invalid:失效,不能再用
最典型的状态流转
记住一个最常见场景就够了:
- A 核心第一次读某条数据:如果别的核心都没有,这条 Cache Line 在 A 中是
E - B 核心也来读:A 和 B 都变成
S - A 核心要写:先让别的核心对应副本失效,A 写完后变成
M,别人变成I - A 之后继续写:因为已经是
M,可以直接改 - A 将来替换这条
M状态 Cache Line:先写回内存
如果你想继续看一致性带来的典型性能问题,可以接着看 伪共享。
继续看
参考主线:小林coding《2.4 CPU 缓存一致性》