CPU 缓存按缓存行(通常 64 字节)而非按变量读写。当两个线程分别修改两个不同变量,但这两个变量恰好落在同一缓存行时,MESI 一致性协议会让该行在两个核之间反复失效、回写、重新加载——逻辑上无共享,物理上却互相干扰,性能可能差一个数量级,这就是伪共享。

解决方案是让热变量独占缓存行:1)手动填充——在字段前后各加 7 个 long 占位字段,把对象撑到一行装不下两个热字段(Disruptor 的 Sequence 就是这么做的,注意 JVM 可能重排或优化掉无用字段,有继承时填充还可能被压缩);2)@Contended 注解(jdk.internal.vm.annotation,JDK 8+)——JVM 自动填充 128 字节,可靠但需要 -XX:-RestrictContended 才允许业务代码使用;3)重排字段,把「同线程访问的字段聚一起、不同线程的字段隔开」。典型场景:多线程各自更新的计数器数组(LongAdder 的 Cell 正是 @Contended)、无锁队列的头尾指针。追问方向:为什么 LongAdder 比 AtomicLong 在高竞争下快(分段 + 伪共享防护的组合)、如何实测伪共享(JMH 对照实验、perf c2c 工具观测 HITM)、缓存行大小在不同架构的差异(ARM 服务器 64/128 字节)。

(约 450 字)