LongAdder
LongAdder:高并发下的高效原子累加器
在高并发场景中,AtomicLong虽然能保证原子性,但大量线程竞争同一个变量时,CAS 操作的失败重试会导致CPU 自旋开销激增。JDK 8 引入的LongAdder通过分散热点的设计,显著提升了高并发下的累加性能,成为计数器场景的首选工具。
LongAdder 的核心设计思想
LongAdder的核心是分而治之:将一个全局计数器拆分为多个局部计数器(Cell数组),线程优先操作自己对应的局部计数器,最后通过累加局部计数器的值得到全局结果。
- 低并发场景:直接操作
base变量(类似AtomicLong); - 高并发场景:线程分散到不同的
Cell中进行累加,减少竞争。
LongAdder 的内部结构
public class LongAdder extends Striped64 implements Serializable {
// 存储局部计数器的数组(延迟初始化)
transient volatile Cell[] cells;
// 基础值(低并发时直接使用,或作为备用)
transient volatile long base;
// 自旋锁标识(0:无锁;1:被占用,用于初始化/扩容cells或创建Cell)
transient volatile int cellsBusy;
// 局部计数器Cell类(使用@Contended避免伪共享)
.misc.Contended
static final class Cell {
volatile long value; // 存储局部累加值
Cell(long x) { value = x; }
// CAS操作更新value
final boolean cas(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
}
// 省略Unsafe相关代码...
}
}
关键细节:
- @Contended 注解:避免
Cell数组元素因 CPU 缓存行共享导致的伪共享问题(提升缓存利用率); - volatile 修饰:
cells、base、Cell.value均用volatile保证可见性; - cellsBusy:通过 CAS 控制
cells数组的初始化、扩容和Cell创建的原子性。
核心方法解析:add (long x)
add方法是LongAdder的核心,逻辑是优先操作 Cell,失败则退化为操作 base:
