LongAdder 如何在高并发下用 CAS 实现比 AtomicInteger 更高性能?
这是一个非常典型也非常重要的并发性能优化问题。
1、简要结论:
LongAdder是AtomicLong的性能增强版,在高并发场景下比 AtomicLong 更高效,其核心是:使用分段(Striped)思想 + CAS 操作,避免大量线程争抢同一个变量。
2、为什么 AtomicLong 会成为性能瓶颈?
AtomicLong 的底层实现是基于 CAS(Compare-And-Swap) 的:
public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
⚠️ 问题:
- 所有线程都在争抢一个变量(如
count) - 并发高时,
CAS成功率变低,大量自旋,CPU 开销大
3、LongAdder 的设计核心:分段计数
👉 类似“分区统计”:把一个变量拆成多个,分摊竞争压力
+-----------+-----------+-----------+-----------+
| Cell[0] | Cell[1] | Cell[2] | ... |
| 5 | 3 | 4 | |
+-----------+-----------+-----------+-----------+
- 每个线程对不同的 Cell 操作
- 最后通过所有 Cell 的值 + 基础值(
base)求和得出总值
4、源码结构(简化)
public class LongAdder extends Striped64 {
// 分段数组(懒初始化)
transient volatile Cell[] cells;
// 低竞争时使用的基础值
transient volatile long base;
}
5、increment() 方法实现逻辑(简化)
public void increment() {
Cell[] as; long b; int m, h;
if ((as = cells) != null || !casBase(b = base, b + 1)) {
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 ||
as[h & m] == null || !(uncontended = as[h & m].cas(v, v + 1)))
longAccumulate(1L, null, uncontended);
}
}
⛓️ 解释流程:
- 优先尝试
CAS增加base(低并发下走这里) - 如果失败,尝试对当前线程的 Cell 位置进行
CAS增加 - 如果还失败,说明竞争严重,调用
longAccumulate():
- 初始化或扩展
cells数组 - 重试插入到新的 Cell 槽位
6、求和操作(sum())
public long sum() {
Cell[] as = cells;
long sum = base;
if (as != null) {
for (Cell a : as) {
if (a != null)
sum += a.value;
}
}
return sum;
}
⚠️
sum()不是原子操作,仅做近似统计(适用于统计计数、QPS、请求量等)
7、LongAdder vs AtomicLong 性能对比
| 指标 | AtomicLong | LongAdder |
|---|---|---|
| CAS 重试开销 | 高(集中在单变量) | 低(分段分散) |
| 高并发性能 | 一般,容易争抢 | 优秀,避免热点竞争 |
| 空间开销 | 低 | 稍高(多个 Cell 占内存) |
| 精度 | 精确 | 高并发下可能近似(非原子) |
| 适用场景 | 低并发/精准计数 | 高并发/统计型计数(QPS) |
8、实际使用建议
| 应用场景 | 推荐使用 |
|---|---|
| Web 访问计数器 | ✅ LongAdder(吞吐量更高) |
| 并发限流统计 | ✅ LongAdder |
| 交易系统计数(需精确) | ❌ 用 AtomicLong 或加锁 |
| 计量指标上报(Prometheus) | ✅ LongAdder |
9、参考链接
- 🔗 Java 源码:LongAdder
- 🔗 JDK Concurrency 原始设计者 Doug Lea 的 Striped64 论文
- 🔗 官方文档:
LongAdder - 🔗 阿里 P8 分析:LongAdder 是怎么做到比 AtomicLong 快的
10、总结记忆口诀
AtomicLong 高竞争易瓶颈,LongAdder 分段巧避锋;base 优先,cell 分摊,近似统计快如风。
更多详细内容请关注其他相关文章!