cas高并发变慢源于单点竞争、伪共享和重试风暴;longadder通过分段cell+哈希定位+base聚合实现降竞争,吞吐达atomicinteger的3–5倍。

CAS 本身不直接分段,但分段思想常与 CAS 协同使用,解决高并发下“单点竞争”和“重试风暴”问题。核心思路是:把一个全局共享变量拆成多个局部变量,各自用 CAS 独立更新,最后再聚合结果。
为什么单个 CAS 在高并发下会变慢
当大量线程频繁对同一个 AtomicInteger 执行 increment(),会出现:
- CAS 失败率飙升——每次失败都要重试,CPU 白耗在循环比较上
- 缓存行伪共享(False Sharing)——多个 CPU 核心反复刷新同一缓存行,拖慢整体吞吐
- 写冲突集中——所有更新都挤在内存中同一个地址,硬件层面也成瓶颈
LongAdder 是分段 + CAS 的典型实现
它不是维护一个值,而是维护一个 cell 数组,每个 cell 是一个带 volatile long 的单元:
- 线程首次更新时,尝试用 CAS 写入 base 字段(类似普通 AtomicInteger)
- 一旦发生竞争,就哈希选择一个 cell,用 CAS 更新该 cell 的 value
- 后续同一线程优先复用同一个 cell,减少跨线程干扰
- sum() 时遍历所有非空 cell,加上 base 值,得到最终结果
手动实现分段 CAS 的关键设计点
若需自定义分段逻辑(比如统计多维度指标),注意三点:
- 哈希分散要均匀:用 ThreadLocalRandom 或线程 ID 做 hash,避免某些 cell 过热
- cell 数组大小建议为 2 的幂:便于用位运算取模,提升定位效率
- 预留扩容能力:当某 cell 持续竞争时,可动态增加 cell 数量(类似 ConcurrentHashMap 的扩容协助机制)
适用场景与避坑提醒
分段 CAS 不是万能方案:
- 适合高写、低读的累加类场景(如 QPS 统计、错误计数)
- 不适合需要强实时一致性的场景(如账户余额),因为 sum() 是最终一致,非即时精确
- 不要滥用——如果并发线程数远小于 16,分段反而增加内存和遍历开销
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











