1. 核心设计思想:分散竞争
LongAdder
为解决高并发下 AtomicLong
的 CAS 竞争问题,采用 分段累加 的策略:
- 无竞争时:直接累加
base
变量(类似AtomicLong
)。 - 有竞争时:将累加操作分散到多个
Cell
单元,降低冲突概率。
2. 核心类与变量
-
父类
Striped64
:实现核心逻辑。abstract class Striped64 extends Number { transient volatile Cell[] cells; // 分段累加单元数组 transient volatile long base; // 基础值(无竞争时使用) transient volatile int cellsBusy; // 扩容/初始化锁(CAS 控制) }
-
Cell
内部类:避免伪共享。@jdk.internal.vm.annotation.Contended // 缓存行填充 static final class Cell { volatile long value; Cell(long x) { value = x; } }
3. add() 方法流程
源码简析(JDK 17):
public void add(long x) {
Cell[] cs; long b, v; int m; Cell c;
// 1. 尝试直接累加 base(无竞争)
if ((cs = cells) == null && !casBase(b = base, b + x)) {
// 2. CAS 失败,存在竞争 → 初始化或扩容 cells
boolean uncontended = true;
// 3. 计算线程哈希,定位 Cell
int h = getProbe();
if (cs == null || (m = cs.length - 1) < 0 ||
(c = cs[m & h]) == null ||
!(uncontended = c.cas(v = c.value, v + x)))
// 4. 进入分段累加逻辑
longAccumulate(x, null, uncontended, h);
}
}
4. longAccumulate() 分段累加逻辑
该方法处理 Cell
数组的初始化、扩容及线程哈希冲突:
-
步骤 1:初始化
cells
数组if (cells == null) { // 未初始化 if (casCellsBusy()) { // 获取 cellsBusy 锁 try { if (cells == null) { cells = new Cell[2]; // 初始容量为 2 } } finally { cellsBusy = 0; // 释放锁 } } }
-
步骤 2:线程哈希冲突处理
int h = advanceProbe(h); // 重新生成哈希码,减少冲突
-
步骤 3:扩容
cells
数组if (n >= NCPU || cells != cs) // 达到 CPU 核数上限或已被扩容 → 停止扩容 break; if (casCellsBusy()) { // 获取锁 try { cells = Arrays.copyOf(cs, n << 1); // 容量翻倍 } finally { cellsBusy = 0; } }
5. sum() 方法:汇总结果
public long sum() {
Cell[] cs = cells;
long sum = base;
if (cs != null) {
for (Cell c : cs)
if (c != null)
sum += c.value;
}
return sum;
}