CPU缓存一致性问题中,为了保证多CPU之间对于同一个变量的数据一致性,我们需要让多CPU之间有办法进行互相同步,总线嗅探 可以让各个CPU之间的读写事件互相传递,比如CPU A写了变量i,那就需要把这份脏数据同步到其他核心比如 核心 B,那就需要使用广播的机制。(总线嗅探的工作机制可以这么去理解)
同时还需要MESI协议,这个协议可以保证对于同一变量在多个CPU之间串行化。
用一个具体的例子,配合状态变化图,彻底讲清楚MESI协议如何保证多核CPU的缓存一致性。
1. 初始状态
- 变量
i:初始值为0,存储在内存中。 - CPU核心:双核(核心A、核心B),各自的L1 Cache初始为空。
- Cache Line状态:所有Cache Line初始为 Invalid(无效)。
内存: i = 0
核心A Cache: i -> Invalid
核心B Cache: i -> Invalid
2. 核心A首次读取 i
- 动作:核心A从内存加载
i到自己的Cache。 - 状态变化:
- 因为其他核心没有缓存
i,核心A独占数据。 - Cache Line状态变为 Exclusive(独占)。
- 因为其他核心没有缓存
内存: i = 0
核心A Cache: i = 0 (Exclusive)
核心B Cache: i -> Invalid
✅ 关键点:Exclusive状态下,核心A可直接修改
i,无需通知其他核心。
3. 核心B读取 i
- 动作:核心B尝试读取
i,发现核心A已缓存。 - 总线嗅探:核心A通过总线将
i=0传给核心B。 - 状态变化:
- 两核心的Cache Line均变为 Shared(共享)。
内存: i = 0
核心A Cache: i = 0 (Shared)
核心B Cache: i = 0 (Shared)
✅ 关键点:Shared状态下,任何核心修改
i需先广播无效化(Invalidate)其他核心的Cache。
4. 核心A修改 i(i = 1)
- 动作:
- 核心A广播 Invalidate 信号,要求其他核心的
i失效。 - 核心B收到信号,将
i的Cache Line标记为 Invalid。 - 核心A更新
i=1,状态变为 Modified(已修改)。
- 核心A广播 Invalidate 信号,要求其他核心的
内存: i = 0 (未更新)
核心A Cache: i = 1 (Modified) // 脏数据,未同步到内存
核心B Cache: i -> Invalid // 已失效
✅ 关键点:Modified状态下,数据仅存在于核心A的Cache,与内存不一致。
5. 核心B再次读取 i
- 动作:
- 核心B发现自己的
i为 Invalid,向总线发起读请求。 - 核心A嗅探到请求,将脏数据
i=1写回内存,并传给核心B。 - 两核心的Cache Line状态均变为 Shared。
- 核心B发现自己的
内存: i = 1 (已同步)
核心A Cache: i = 1 (Shared)
核心B Cache: i = 1 (Shared)
✅ 关键点:脏数据回写后,两核心重新共享一致数据。
6. 核心A再次修改 i(i = 2)
- 状态:此时
i为 Shared。 - 动作:
- 核心A再次广播 Invalidate,使核心B的
i失效。 - 核心A直接修改
i=2,状态变为 Modified。
- 核心A再次广播 Invalidate,使核心B的
内存: i = 1 (未更新)
核心A Cache: i = 2 (Modified) // 新脏数据
核心B Cache: i -> Invalid
状态转换图
[Invalid] ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←
↑ Load (首次读) ↑ Invalidate (其他核心修改)
| |
[Exclusive] → Shared by Other Core → [Shared]
| ↓
| Write (直接修改) Invalidate + Write → [Modified]
↓ ↑
[Modified] → Write Back to Memory → [Shared]
关键总结
- Exclusive:数据仅存在于一个核心,可无竞争修改。
- Shared:多核心共享数据,修改前需广播无效化。
- Modified:数据已修改且未同步到内存,其他核心读取时触发回写。
- Invalid:数据失效,需重新从内存或其他核心加载。
MESI的精髓:通过状态机减少不必要的总线通信(如Exclusive/Modified状态下的本地修改),同时严格保证多核数据一致性。
991

被折叠的 条评论
为什么被折叠?



