缓存一致性与 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:失效,不能再用

最典型的状态流转

记住一个最常见场景就够了:

  1. A 核心第一次读某条数据:如果别的核心都没有,这条 Cache Line 在 A 中是 E
  2. B 核心也来读:A 和 B 都变成 S
  3. A 核心要写:先让别的核心对应副本失效,A 写完后变成 M,别人变成 I
  4. A 之后继续写:因为已经是 M,可以直接改
  5. A 将来替换这条 M 状态 Cache Line:先写回内存

如果你想继续看一致性带来的典型性能问题,可以接着看 伪共享

继续看


参考主线:小林coding《2.4 CPU 缓存一致性