MESI 协议:CPU 是怎么保证缓存一致的? 🤔 一、CPU 架构师为什么需要 MESI 协议 1970 年代,CPU 直接从内存读数据,内存足够快。到了 1990 年代,CPU 主频飙到几百 MHz,内存还是几十 ns 的访问延迟——一颗 200MHz 的 CPU,等一次内存读取等于浪费十几个指令周期。CPU 架构师的应对方案是加缓存:把热数据放在离核心最近的地方。
缓存解决了速度问题,但制造了一个新问题:多核 CPU 中,同一个内存地址可能在多个核心的私有缓存中各有副本。 Core A 修改了 count = 1,Core B 的缓存中 count 还是 0——Core B 基于过期数据继续算,结果全错。
这个问题的本质不是"哪个值更正确",而是各个核心对同一地址的数据要有统一的认知——这就是缓存一致性(Cache Coherence)。没有它,多核处理器就等于多个单核处理器各算各的,合不起来。
Intel 架构师给出的答案就是 MESI 协议。它在每个缓存行上维护一个 2 位状态机——M(Modified,已修改且独占)、E(Exclusive,独占且干净)、S(Shared,多副本共享)、I(Invalid,本副本无效)。核心之间通过总线监听彼此的读写操作,自动在四种状态之间切换。
MESI 保证两件事:对同一地址的写操作最终对所有核心可见;所有核心对同一地址的写操作有一个全局一致的顺序(serialization)。它不是"所有核心时刻看到完全相同的值"——电信号传递本身有延迟,那是不可能的。它保证的是:给定足够时间,一致性一定会达成。
🏗️ 二、CPU 缓存层级结构 💾 2.1 三级缓存布局 现代多核 CPU 的缓存分为三级。L1/L2 每个核心私有,L3 所有核心共享:
flowchart TD %% 半暗底色 + 高亮描边:完美适配博客深色/浅色双主题 %% classDef highlight fill:#431407,stroke:#ea580c,stroke-width:2px,color:#fed7aa,font-weight:bold; classDef data fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#bbf7d0,font-weight:bold; classDef process fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#e5e7eb; subgraph Core0["CPU Core 0"] L1_0[L1 Cache\n32KB 指令 + 32KB 数据] L2_0[L2 Cache\n256KB ~ 1MB] end subgraph Core1["CPU Core 1"] L1_1[L1 Cache\n32KB 指令 + 32KB 数据] L2_1[L2 Cache\n256KB ~ 1MB] end L1_0 --> L2_0 L1_1 --> L2_1 L2_0 --> L3[L3 Cache / LLC\n所有核心共享\n数MB ~ 数十MB] L2_1 --> L3 L3 --> MEM[主内存RAM] class L1_0,L1_1,L2_0,L2_1,L3 data; class Core0,Core1 highlight; class MEM process; 关键点:
...