LongAdder比AtomicLong更适合高并发计数,因其采用分段累加策略减少线程竞争;适用于写多读少的指标统计场景,但不保证强实时读取。

LongAdder 是 Java 8 引入的高性能计数器,专为高并发场景优化,比 AtomicLong 更适合频繁更新、低频读取的计数场景。它通过“分段累加 + 最终汇总”的策略,显著减少线程竞争,避免 CAS 自旋瓶颈。
为什么 LongAdder 比 AtomicLong 更适合高并发计数
AtomicLong 依赖单个 volatile 变量 + CAS 循环,在多核高争用时,大量线程反复失败重试,导致 CPU 浪费和缓存行伪共享(false sharing)。LongAdder 则把计数分散到多个 Cell 中,每个线程优先尝试更新自己的 Cell;只有发生竞争时才扩容或尝试其他 Cell。最终 sum() 时才合并所有 Cell 值 —— 写操作几乎无竞争,读操作虽需遍历但频率通常远低于写。
如何正确使用 LongAdder 进行计数
使用非常简洁,但要注意语义和时机:
- 初始化:直接 new LongAdder(),无需额外配置
- 累加:调用 add(long x),线程安全,推荐替代 ++ 或 +=
- 获取当前值:用 sum(),注意它不是强实时快照(可能略滞后),但最终一致
- 重置计数:不支持 clear(),常见做法是新建实例;若需复用,可用 sumThenReset()(Java 1.8u262+)
示例:
LongAdder counter = new LongAdder();
// 多线程中
counter.add(1);
// 最终统计
long total = counter.sum();
适用场景与关键注意事项
LongAdder 不是万能替代品,要匹配其设计意图:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- ✅ 适合:请求计数、QPS 统计、采样计数、日志打点等「写多读少、允许短暂延迟」的指标类场景
- ❌ 不适合:需要严格实时读取的场景(如限流阈值判断)、依赖原子性复合操作(如“先读再条件更新”)
- ⚠️ 注意:sum() 结果可能比最新写入慢几个操作(因 Cell 更新异步),但不会丢失数据;若需强一致性读,仍应回退用 AtomicLong
- ⚠️ 内存开销略高:初始仅一个 base 字段,竞争时动态创建 Cell 数组,极端情况下可能达几十个对象,但远小于线程数
对比 AtomicLong 的简单压测结论(参考)
在 32 线程、纯 increment 场景下(JDK 17):
- AtomicLong 吞吐约 800 万 ops/s,CPU 利用率高,CAS 失败率超 60%
- LongAdder 吞吐可达 2500 万+ ops/s,失败率趋近于 0,扩展性明显更好
差距随线程数增加而拉大,尤其在多 socket 服务器上更显著。


















