JMM 底层 MESI 协议完整详解

📅 2026/7/15 3:49:00
JMM 底层 MESI 协议完整详解
目录一、前置基础二、MESI 四种状态核心脏数据定义三、关键总线消息状态流转依赖的通信四、完整状态流转分场景梳理场景 1CPU 首次读取变量主存无缓存副本场景 2CPU0 (E) 执行写操作修改数据场景 3CPU0 (E)CPU1 同时读取同一变量场景 4多个 CPU 处于 S共享任意 CPU 执行写场景 5CPU0 是 M脏数据其他 CPU 发起 Read 读请求场景 6CPU0 是 M其他 CPU 发起写RFO 请求场景 7任意状态收到 Invalidate 失效广播场景 8M 态缓存行主动刷回主存缓存淘汰五、流转流程图文字总结六、高频面试重点总结补充区分MESI vs JMM一、前置基础MESI 是CPU 缓存一致性协议解决多核 CPU 各自私有 L1/L2 缓存与主存之间的数据同步问题是 Java 内存模型JMM实现volatile、锁、可见性的硬件底层支撑。 CPU 缓存最小存储单元缓存行Cache Line每条缓存行带有一个 2bit 状态标记对应 MESI 四种状态。二、MESI 四种状态核心缓存行只会处于下面四种状态之一用首字母命名 M/E/S/I状态全称中文核心含义数据是否脏DirtyMModified修改态当前 CPU 缓存行数据已修改和主存不一致本 CPU 独有这份最新数据其他 CPU 无副本✅ 脏数据EExclusive独占态当前 CPU 独有该缓存行缓存数据和主存完全一致其他 CPU 没有此缓存行副本❌ 干净SShared共享态多个 CPU 缓存中同时持有该缓存行副本所有缓存副本数据和主存一致❌ 干净IInvalid无效态当前 CPU 缓存行数据作废不能读取必须重新从主存拉取最新数据— 无有效数据脏数据定义只有MModified状态的缓存行是脏数据缓存内的值 ≠ 主存的值。 后续 CPU 需要该缓存行时持有 M 状态的 CPU 必须先把脏数据刷回主存再响应其他核请求。三、关键总线消息状态流转依赖的通信多核通过系统总线广播消息互相感知核心 4 类消息ReadCPU 向总线发请求读取主存某缓存行数据Read OwnershipRFO读并独占拿到数据后直接置为 M用于写操作其他核收到后把对应缓存行置 IInvalidate失效广播通知所有其他 CPU 把对应缓存行标记为 IWriteback把 M 态脏缓存行刷写回主存四、完整状态流转分场景梳理场景 1CPU 首次读取变量主存无缓存副本CPU0 发起 Read 请求总线广播其他 CPU 无该缓存行主存返回数据给 CPU0 缓存无其他核持有副本 → 缓存行设为E独占流转I → E场景 2CPU0 (E) 执行写操作修改数据CPU0 独占缓存无需通知其他核直接修改缓存行状态变为M修改 / 脏流转E → M场景 3CPU0 (E)CPU1 同时读取同一变量CPU1 发 Read 广播CPU0 监听到请求自身是 E 状态把缓存行状态改为 S主存同步数据给 CPU1CPU1 缓存行设 S 最终两者都是 S 态 流转E → SI → S场景 4多个 CPU 处于 S共享任意 CPU 执行写以 CPU0 写为例CPU0 发Invalidate广播通知所有其他 CPU 失效该行CPU1/CPU2 收到消息本地缓存行直接置 ICPU0 收到所有核的失效确认后修改本地缓存状态切换 M 流转S → M其他核S → I场景 5CPU0 是 M脏数据其他 CPU 发起 Read 读请求CPU1 广播 ReadCPU0 监听到自身是 M脏先执行 Writeback把缓存数据刷入主存CPU0 将自身缓存行改为 S主存把最新数据发给 CPU1CPU1 缓存行设 S 流转M → SI → S场景 6CPU0 是 M其他 CPU 发起写RFO 请求CPU1 发 RFO读并独占写广播CPU0 监听到先 Writeback 脏数据回主存本地缓存置 I主存返回数据给 CPU1CPU1 直接设 M 流转M → II → M场景 7任意状态收到 Invalidate 失效广播E / S 收到失效直接变为 IM 收到失效先刷回主存再变 I 流转E→I、S→I、M→I场景 8M 态缓存行主动刷回主存缓存淘汰CPU 缓存空间不足淘汰 M 状态缓存行执行 Writeback 写回主存本地缓存行变为 I 流转M → I五、流转流程图文字总结初始所有核缓存行都是 I单 CPU 读无副本I → EE 被其他核读E → SE 本地写E → MS 本地写S → M其余 S 变 IM 被其他核读M 刷回主存 → M→S请求核 I→SM 被其他核写M 刷回主存 → M→I请求核 I→M任意状态收到失效指令全部转为 I六、高频面试重点总结哪种是脏数据只有 Modified (M) 状态缓存与主存不一致E/S 都和主存同步是干净缓存。volatile 的底层逻辑写操作会触发 Invalidate 广播强制其他 CPU 缓存失效实现可见性本质依赖 MESI 的缓存失效机制。MESI 性能问题频繁读写共享变量会产生大量总线风暴反复广播 Invalidate/RFO也就是伪共享解决方案是缓存行填充。I 无效态本地缓存数据作废读取必须重新走总线请求主存或其他 CPU 的 M 缓存。E 独占态优势独占时写不需要广播消息性能极高无总线开销。补充区分MESI vs JMMMESICPU 硬件缓存一致性协议解决多核缓存数据同步JMMJava 抽象内存模型屏蔽不同 CPU 缓存、操作系统内存模型差异定义可见性、有序性、原子性规范关系JMM 的内存可见性、禁止指令重排内存屏障是基于 MESI 与 CPU 内存屏障StoreLoad/StoreStore 等实现的。