LongAdder 和 DoubleAdder 比 AtomicLong 快,因其采用分段累加+最终合并机制,减少CAS自旋;但仅适用于写多读少场景,sum()非原子快照且不清理空闲cell,API更窄,不支持compareAndSet等操作。

DoubleAdder 和 LongAdder 为什么比 AtomicLong 快
因为它们用「分段累加 + 最终合并」代替了全局 CAS 自旋。AtomicLong 在高并发下大量线程争抢同一个值,失败重试成本高;而 DoubleAdder 和 LongAdder 内部维护一个 cell 数组,线程先尝试往自己的 slot 累加,冲突少、自旋少。
但这个优势只在「写多读少」场景明显——比如统计请求量、埋点计数、实时聚合指标。如果频繁调用 sum(),反而可能因遍历 cell 数组带来开销。
-
sum()不是原子快照:执行过程中其他线程仍可修改,结果是近似实时值,不是严格某一时刻的精确和 - 初始状态为 0,但
sum()返回前不会自动压缩或清理空闲 cell,长期运行后 cell 数组可能膨胀(尤其在突发流量后又归于平静) - 不支持 compareAndSet、getAndIncrement 等原子操作,API 比
AtomicLong更窄,仅适合“只加不查”的计数器角色
什么时候该用 LongAdder 而不是 DoubleAdder
看你要累加的是整数还是浮点数——别被名字误导:LongAdder 是 long 类型,DoubleAdder 是 double 类型,二者底层实现不同,不能混用。
DoubleAdder 内部用 long 存储 double 的 bit 表示(类似 Double.doubleToRawLongBits),再通过 CAS 操作 long 字段模拟浮点累加,所以它比 LongAdder 多一层转换开销,且存在浮点精度丢失风险(比如连续加 0.1 加十次,结果可能不是 1.0)。
立即学习“Java免费学习笔记(深入)”;
- 计数器、QPS、UV/PV 统计 → 无条件选
LongAdder - 需要累加带小数的度量值(如平均响应时间毫秒值、百分比)→ 先确认是否真需要 float/double 精度;多数监控场景其实可以转成 nanos 或万分之一单位用
LongAdder避免误差 - 必须用 double 且能接受误差 → 才考虑
DoubleAdder,但要留意sum()返回的是double,不是原始累加过程的数学精确值
sum() 和 sumThenReset() 的行为差异与线程安全边界
sum() 是只读操作,线程安全,但不阻塞写入;sumThenReset() 是“读+清零”原子操作,内部会把所有 cell 值归零,并返回归零前的总和。
注意:sumThenReset() 并非完全原子——它无法阻止其他线程在你读完 cell[i] 后、清零前再次向该 cell 写入。所以它的“清零”是对当前已知 cell 的批量归零,新来的写入会落在新分配或已有非空 cell 上。
- 做周期性上报(如每 10 秒 push 一次当前累计值并清零)→ 用
sumThenReset(),但需接受两次上报之间可能漏掉极少量新增值(概率低,但存在) - 只是临时查看当前估算值(如健康检查暴露指标)→ 用
sum(),更轻量 - 不要在循环里反复调用
sumThenReset()并期望得到互斥的区间值——并发写入可能导致某次 reset 后立刻又被写入,下次 sum 时包含“本该属于上一周期”的数据
常见误用:当成 AtomicLong 的直接替代品
很多人看到“高性能”就直接把代码里的 AtomicLong 替成 LongAdder,结果发现单元测试失败或者逻辑异常——根本原因是语义变了。
AtomicLong.get() 返回精确当前值;LongAdder.sum() 返回估算值;AtomicLong.incrementAndGet() 返回自增后的精确值;LongAdder.increment() 没有返回值。
- 如果你的业务依赖「每次自增都拿到最新值并做判断」(比如限流器判断是否超阈值),就不能用
LongAdder,必须保留AtomicLong或改用Striped64子类外的方案 - 初始化后未调用任何
add()或increment(),sum()返回 0,看起来没问题,但掩盖了“是否真被写入过”的事实——调试时容易误判数据通路 - Spring Bean 中注入单例
LongAdder用于跨请求计数?可以,但要注意它没有内置 reset 机制,长期运行后sum()可能越来越大,监控告警阈值得按趋势设计,不能写死
最常被忽略的一点:这两个类都不是为「强一致性读写」设计的。它们的快,本质是用一致性换性能。用之前先想清楚——你到底要的是“快”,还是“看起来快但其实不准”。








