低并发时 AtomicLong 更快,高并发时 LongAdder 明显胜出:单线程至≤4线程下AtomicLong快约30%,因LongAdder首次竞争需初始化;≥8线程时LongAdder吞吐量可达AtomicLong的4.9~56倍,依赖分段累加降低CAS冲突;AtomicLong.get()精确即时,LongAdder.sum()最终一致且开销随cells增长;LongAdder内存占用更高、reset()非线程安全、不支持compareAndSet。

低并发时 AtomicLong 更快,高并发时 LongAdder 明显胜出——这不是理论推测,而是大量 JMH 基准测试反复验证的结果。
单线程与低并发(≤4 线程):AtomicLong 占优
在单线程或线程数不超过 CPU 物理核心数的场景下,AtomicLong 的简单 CAS 操作开销小、无额外内存分配,性能更稳定。
- 典型表现:单线程下 AtomicLong 比 LongAdder 快约 30%
- 原因:LongAdder 初始不创建 cells 数组,但首次竞争时需初始化结构,带来轻微延迟
- 适用场景:ID 生成器、配置计数、日志采样开关等写入频次低、线程数少的逻辑
中高并发(≥8 线程,尤其 > CPU 核心数):LongAdder 性能跃升
当并发线程数超过物理核心数,AtomicLong 的 CAS 竞争急剧加剧,而 LongAdder 通过分段累加有效隔离冲突。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 实测数据(32 核服务器,10 万次/线程):16 线程时 LongAdder 吞吐量是 AtomicLong 的 4.9 倍;64 线程时达 56 倍
- 核心机制:每个线程优先尝试更新自己的 Cell 槽位,失败才退回到 base 或扩容 cells,避免“一个变量被所有线程争抢”
- 适用场景:监控指标计数(QPS、错误数)、秒杀库存扣减、实时统计看板等高频写入场景
读取代价与语义差异:sum() vs get()
两者读操作成本和语义不同,直接影响业务逻辑设计。
立即学习“Java免费学习笔记(深入)”;
- AtomicLong.get() 是即时、精确值,开销极小(一次 volatile 读)
- LongAdder.sum() 需遍历所有 cells 并累加 base,耗时随 cells 数量线性增长;且结果是“最终一致”,非严格实时
- 注意:sum() 不加锁,但若调用期间有其他线程正在扩容 cells,可能短暂包含部分未同步的值(实践中误差可忽略)
内存与重置限制:空间换时间的现实代价
LongAdder 的高性能是以内存占用和灵活性折损为前提的。
- 内存开销:cells 数组默认最多 2^CPU核心数 个槽位(如 64 核机器可达 64 个 Cell 对象),每个 Cell 含 long + padding,比 AtomicLong 多占用数 KB 至数十 KB
- reset() 方法非线程安全:仅适用于确认无并发写入的场景(如定时归零统计),否则可能丢失中间更新
- 不支持 compareAndSet:无法实现条件更新逻辑,这是 AtomicLong 的独有能力

















