跳到正文
Elaine Blog
返回

CPU 缓存、伪共享与 Disruptor

并发编程

两个线程即使更新不同字段,也可能因字段落在同一缓存行而互相使缓存失效,这叫伪共享。它是硬件与对象布局共同产生的 性能问题,只能通过目标机器上的可靠基准确认,不能靠字段相邻就下结论。

Table of contents

Open Table of contents

运行实验框架

下载伪共享实验样例下载, 运行:

java -cp target/classes dev.elaine.concurrency.FalseSharingSample

两个平台线程同时更新同一对象中的两个 volatile long,程序输出最终值和耗时。这个结果只证明样例执行完成,不是基准 结论:JIT、字段布局、CPU 拓扑、频率调整和系统负载都会影响单次数字。

缓存行为什么会竞争

CPU 通常按缓存行在核心之间传递一致性状态,而不是按 Java 字段。若核心 A 写 left,核心 B 写同一缓存行中的 right, 整行所有权会来回转移。业务变量没有共享,硬件传输单元却共享,因此称为“伪”共享。

volatile 还要求特定可见性和有序性,不等于每次操作直接访问主内存。实际协议由 CPU 架构和 JVM 生成代码决定。

怎样验证和修复

用 JMH 建立两组实现:字段可能相邻的版本,以及经过填充或分离对象的版本。配置多个 Fork、足够预热、固定核心或记录 CPU 拓扑,并同时观察吞吐和硬件缓存事件。

可选修复包括:

手工添加若干 long 填充不保证跨 JDK 字段布局稳定,也会增加内存占用。

Disruptor 解决什么问题

LMAX Disruptor 是第三方低延迟并发库。它使用预分配环形缓冲区、序号协调和等待策略,让生产者与消费者减少分配和锁 竞争。它适合事件结构固定、吞吐和尾延迟要求高、团队能管理等待策略与消费拓扑的场景。

Disruptor 不是通用消息队列:它不自动提供跨进程持久化、消费者离线恢复或网络传输。普通业务任务先使用有界 BlockingQueue,测得瓶颈后再比较 Disruptor。

下一步

阅读虚拟线程、固定与观测,用更轻量的线程承载大量阻塞式任务。


分享这篇文章:

上一篇
ThreadLocal 泄漏与请求上下文治理
下一篇
虚拟线程、固定与观测