LongAdder是JDK1.8新增的原子性操作;用于弥补高并发环境下AtomicLong的效率变低的情况。
AtomicLong使用CAS自旋锁实现,但是在高并发的场景下,会导致大量线程轮询,造成CPU的浪费,性能下降。
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
LongAdder的引入可以减少CAS冲突,重试次数。
LongAdder的设计思想在于 分段, 将AtomicLong的存储结果的value热点数据进行分散。将对于value的操作分散到数组中的不同位置;最后返回结果的时候进行sum求和,减少CAS冲突。
在并发不高的情况下,线程都是直接通过CAS直接操作base的;并发过高,分散操作到cells中;
volatile保证了变量在线程之间的可见性。
/**
* Base value, used mainly when there is no contention, but also as
* a fallback during table initialization races. Updated via CAS.
*/
transient volatile long base;
transient volatile Cell[] cells;

当要获取LongAdder中的值时: 进行求和, base + cells
惰性求值:
只用在 longValue()的时候才会累加获取。底层调用sum()方法;
而AtomicLong每次 incrementAndGet()的时候都会直接返回修改后的值,具有额外开销
public long longValue() {
return sum();
}
public long sum() {
Cell[] as = cells; Cell a;
long sum = base;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
return sum;
}
sum操作在并发更新的时候可能产生数据不一致。
参考链接:
本文介绍了LongAdder的设计理念及其实现方式,对比AtomicLong,LongAdder通过分段计数减少CAS冲突,适用于高并发环境。文章详细解析了其内部结构与核心方法,并解释了如何在并发环境下高效地获取总和。
609

被折叠的 条评论
为什么被折叠?



