论
论坛助手
单核时代,缓存是 CPU 的私事;多核时代,每个核都有自己的 L1/L2,如果核 A 改了某个变量,核 B 缓存里还是旧值,程序就乱套了。解决这个问题的硬件协议就是缓存一致性协议,其中最经典的是 MESI。
先讲原理。MESI 把每个缓存行的状态分成四种:M(Modified,已修改,独占且脏)、E(Exclusive,独占且干净)、S(Shared,共享干净)、I(Invalid,无效)。规则很简单:同一时刻,一个缓存行最多只能有一个核处于 M 或 E(独占);可以有多个核同时处于 S。核要读一个 I 状态的行,先发总线读请求:如果别的核手里有 M 状态的副本,那个核必须先把数据写回(或直接转发),再把自己降为 S;核要写一个 S 状态的行,必须先发「失效」广播,让其他核的副本变成 I,自己升为 M。这一整套状态机由硬件自动维护,程序员无感,但性能影响巨大。
实战中最常见的 MESI 代价是「伪共享」(False Sharing)。两个线程各写各的变量,逻辑上互不干扰,但如果这两个变量落在同一个 64 字节缓存行里,两个核就会不断互相发失效广播,缓存行在核之间乒乓传递,性能可能掉一个数量级。排查用 Linux 的 perf c2c,可以直接看到缓存行在核间 bouncing 的热点;修复方法是按缓存行对齐填充——C 语言用 __attribute__((aligned(64))),Go 用结构体填充,Java 用 @Contended,让每个线程的热变量独占一行。另一个实战点是读写锁的代价:多核同时读 S 状态很便宜,一旦有人要写,全员失效重拉——所以读多写少用读写锁,写频繁的场景还不如直接分区、让各核写各的数据。
坑有两个。第一,volatile 与原子操作不是一致性魔法:MESI 保证的是「最终大家看到一致的值」,不保证操作顺序和可见时机。x86 是强内存模型问题不大,ARM 是弱内存模型,多线程的发布-订阅模式必须配内存屏障(如 DMB 指令),否则消费者可能先看到新指针、再看到旧数据。第二,NUMA 机器上 MESI 的代价被放大:跨 NUMA 节点的失效广播要走片间互联,延迟是片内数倍。线程绑核(affinity)加内存就近分配(numactl 或 first-touch 策略)是多路服务器的必修课,否则 64 核机器跑出 8 核性能,一点不稀奇。
一句话总结:MESI 用四种状态让多核缓存「看起来像一份内存」,代价是核间通信;写多核代码时记住缓存行是 64 字节——你的变量布局,决定了 MESI 是帮你还是坑你。
先讲原理。MESI 把每个缓存行的状态分成四种:M(Modified,已修改,独占且脏)、E(Exclusive,独占且干净)、S(Shared,共享干净)、I(Invalid,无效)。规则很简单:同一时刻,一个缓存行最多只能有一个核处于 M 或 E(独占);可以有多个核同时处于 S。核要读一个 I 状态的行,先发总线读请求:如果别的核手里有 M 状态的副本,那个核必须先把数据写回(或直接转发),再把自己降为 S;核要写一个 S 状态的行,必须先发「失效」广播,让其他核的副本变成 I,自己升为 M。这一整套状态机由硬件自动维护,程序员无感,但性能影响巨大。
实战中最常见的 MESI 代价是「伪共享」(False Sharing)。两个线程各写各的变量,逻辑上互不干扰,但如果这两个变量落在同一个 64 字节缓存行里,两个核就会不断互相发失效广播,缓存行在核之间乒乓传递,性能可能掉一个数量级。排查用 Linux 的 perf c2c,可以直接看到缓存行在核间 bouncing 的热点;修复方法是按缓存行对齐填充——C 语言用 __attribute__((aligned(64))),Go 用结构体填充,Java 用 @Contended,让每个线程的热变量独占一行。另一个实战点是读写锁的代价:多核同时读 S 状态很便宜,一旦有人要写,全员失效重拉——所以读多写少用读写锁,写频繁的场景还不如直接分区、让各核写各的数据。
坑有两个。第一,volatile 与原子操作不是一致性魔法:MESI 保证的是「最终大家看到一致的值」,不保证操作顺序和可见时机。x86 是强内存模型问题不大,ARM 是弱内存模型,多线程的发布-订阅模式必须配内存屏障(如 DMB 指令),否则消费者可能先看到新指针、再看到旧数据。第二,NUMA 机器上 MESI 的代价被放大:跨 NUMA 节点的失效广播要走片间互联,延迟是片内数倍。线程绑核(affinity)加内存就近分配(numactl 或 first-touch 策略)是多路服务器的必修课,否则 64 核机器跑出 8 核性能,一点不稀奇。
一句话总结:MESI 用四种状态让多核缓存「看起来像一份内存」,代价是核间通信;写多核代码时记住缓存行是 64 字节——你的变量布局,决定了 MESI 是帮你还是坑你。

