Skip to content
Java 锁实现与并发细节 · 第 3 篇 / 共 4 篇
领域编程与框架
专题Java 专题
当前序列Java 锁实现与并发细节
阅读位置第 3 篇 / 共 4 篇当前专题第 6 个序列 / 共 10 个序列

AtomicLong 和 LongAdder 怎么选

先说结论

  • 写多读少、竞争激烈的热点计数,LongAdder 往往更合适
  • 需要原子读改写、语义直接、结果实时一致时,AtomicLong 更合适
  • 这不是“谁更高级”的问题,而是“你要的是吞吐,还是要的是精确原子语义”

一、两者最大的差别是什么

1. AtomicLong

它的核心是单点 CAS。
优点是语义直接:

  • incrementAndGet
  • compareAndSet
  • getAndUpdate

都非常明确。

问题在于:
高并发热点下,所有线程都在竞争同一个值,冲突会明显增加。

2. LongAdder

它的思路是“分散热点”。
高并发时,不是所有线程都去抢同一个计数槽,而是分散到多个 cell 上,最后求和。

所以它通常更适合:

  • 高频累加
  • 统计指标
  • QPS 计数器
  • 命中次数统计

二、什么时候更适合 AtomicLong

更适合这些场景:

  • 需要 CAS 语义
  • 需要精确的实时值
  • 读写都比较频繁
  • 竞争并不算特别激烈

比如:

  • 生成递增序号
  • 状态位控制
  • 基于旧值做条件更新

这些场景里,LongAdder 反而不自然,因为它不擅长“拿当前值再做原子判断”。

三、什么时候更适合 LongAdder

更适合这些场景:

  • 写非常多
  • 读相对少
  • 读的时候允许做一次汇总
  • 更关心吞吐,不强调每次读取都是单点强一致视角

比如:

  • 监控计数
  • 接口命中次数
  • 缓存命中统计
  • 分片热点计数

四、最容易踩的坑

1. 以为 LongAdder 可以完全替代 AtomicLong

它更像“高并发统计工具”,不是通用原子变量替代品。

2. 只看压测吞吐,不看读取语义

LongAdder 压测常常更漂亮,但如果你的业务逻辑依赖“读到当前值并马上做判断”,那重点就不是吞吐了。

3. 低并发场景也盲目上 LongAdder

如果竞争不高,AtomicLong 本来就足够简单直接。

总结

AtomicLong 更像“原子变量”,LongAdder 更像“高并发计数器”。前者强调语义和操作完整性,后者强调热点写入下的吞吐表现。先看你的业务是在做控制还是在做统计,基本就知道该选谁了。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读CopyOnWriteArrayList 什么时候值得用适合把 synchronized、CAS、LongAdder 和并发容器的适用边界放到一起看。Java 专题 · Java 锁实现与并发细节同一序列 · 回看前文会更完整CAS 的 ABA 问题怎么理解适合把 synchronized、CAS、LongAdder 和并发容器的适用边界放到一起看。Java 专题 · Java 锁实现与并发细节同专题其他序列 · 共享标签:选型对比锁与 CAS 怎么选适合沿着 JUC、volatile、CAS、AQS 和锁实现这条主线往下看。Java 专题 · Java 并发与锁机制同专题其他序列 · 共享标签:选型对比线程池拒绝策略怎么选适合把线程池参数、拒绝策略、CompletableFuture 和 ForkJoin 放在一起连续看。Java 专题 · Java 线程池与异步编排跨专题关联 · 同场景:方案选型半同步复制和异步复制怎么选适合把 next-key lock、一致性读、复制延迟和分库分表边界放回同一条一致性主线上判断。MySQL 专题 · MySQL 事务、锁与高可用边界跨专题关联 · 同场景:方案选型分词器、Tokenizer 和 IK 到底怎么选适合把分词、复杂查询和深分页放到一起深入看。Elasticsearch 专题 · Elasticsearch 查询与分析细节
继续阅读Java 锁实现与并发细节当前序列第 3 篇 / 共 4 篇当前专题第 6 个序列 / 共 10 个序列
往前看
上一篇CAS 的 ABA 问题怎么理解回到当前序列上一章上一序列JVM 与进程排障从第 1 篇开始:JVM 内存问题怎么分析
往后看
下一篇CopyOnWriteArrayList 什么时候值得用继续当前序列下一章下一序列Java 类加载与运行时细节从第 1 篇开始:双亲委派模型到底解决了什么

把零散经验整理成可查、可复用、可持续更新的企业级知识门户