跳转至

总线加锁机制和 MESI 缓存一致性协议

一、问题

多核 CPU 每个核有自己的缓存,同一个变量可能在多个核的缓存里都有副本。如果核 A 修改了,核 B 的缓存还是旧值,怎么办?

二、总线加锁(最早的方案)

CPU 通过锁总线来保证同一时刻只有一个核访问内存:

LOCK #LOCK
add eax, dword ptr [ebx]

执行时 CPU 锁死系统总线,其他核不能通过总线访问内存。

缺点

  • 性能极差:锁总线期间所有核都不能访问内存。
  • 粗粒度:一个核改一个字节,整个内存都不能访问。

三、MESI 协议

现代 CPU 用 MESI 缓存一致性协议,按缓存行为单位管理状态:

状态 含义
M Modified 当前核修改过,与内存不一致,独占
E Exclusive 缓存行独占,和内存一致
S Shared 多个核都有,和内存一致
I Invalid 无效,需要重新从内存读

四、状态转换

读操作

  • 本地缓存命中(M/E/S):直接用。
  • 未命中:发广播,其他核如果有 M 状态的缓存行,先写回内存。
  • 其他核都没有:变 E;其他核有:变 S。

写操作

  • 当前是 E 或 M:直接写,变 M。
  • 当前是 S:发无效化请求给其他核,它们变 I,自己变 M。
  • 当前是 I:先获得独占权(发广播),再写。

五、为什么用 MESI 而不是总线锁

  • 只锁一个缓存行,不是整个总线。
  • 多核可以同时读(S 状态),不冲突。
  • 写时才做协调。

六、和 Java 的关系

  • volatile 写后插入的 lock 指令,本质就是让缓存行回到 M/E 状态并刷回内存。
  • MESI 是硬件层的一致性,Java 内存模型(JMM)在此基础上定义了更高层的可见性语义。

高频追问

  • MESI 为什么叫这四个字母?Modified / Exclusive / Shared / Invalid。
  • S 状态为什么性能好?多核同时读不用协调。