选 AtomicLong 还是 LongAdder,关键看场景:写少读多、需强一致(如订单号、库存扣减)用 AtomicLong;写多读少、可接受最终一致(如QPS统计、点击数)用 LongAdder,后者在高并发下吞吐量可达前者的56倍。

选 AtomicLong 还是 LongAdder,关键看你的场景里“写得多不多”和“读得准不准”。
写少读多、要绝对精确,用 AtomicLong
比如生成订单号、分配唯一序列 ID、库存扣减这类操作——每次更新都必须准确无误,且读取结果要立刻反映最新状态。AtomicLong 的 get() 是一次 volatile 读,开销极小,值永远强一致。
- 单线程或 ≤4 线程时,它比 LongAdder 快约 30%
- 不依赖额外结构,内存占用仅一个 long(8 字节)
- 支持 compareAndSet,能做条件更新(如“只有当前值为 10 才加 1”)
写多读少、吞吐优先、允许最终一致,用 LongAdder
比如实时监控 QPS、错误数、直播间在线人数、埋点点击统计——这些指标高频写入、低频汇总,短期误差可接受,只要最终总数对就行。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 8 线程起性能反超;64 线程下吞吐量可达 AtomicLong 的 56 倍
- 靠 base + Cell[] 分段累加,把“万人抢一个门”变成“每人走不同通道”
- sum() 需遍历所有 Cell,耗时随并发度上升,且结果是最终一致(非某一时刻快照)
别忽略这些实际限制
LongAdder 不是万能加速器,用错反而添麻烦:
立即学习“Java免费学习笔记(深入)”;
- reset() 方法不是线程安全的,不能在写入同时调用
- 不支持 compareAndSet,没法替代 AtomicLong 做原子条件判断
- 内存占用高:64 核机器上最多可能建 64 个 Cell,每个含 long + 缓存行填充,多占几十 KB
简单决策流程
先问自己三个问题:
- 计数更新是否每秒超过 1000 次?且线程数常超 CPU 核心数?→ 倾向 LongAdder
- 业务逻辑是否依赖“此刻精确值”做判断或分支?→ 必须用 AtomicLong
- 是否需要定时归零但又无法停写?→ LongAdder 的 sumThenReset() 可用,但 reset() 不行

















