1. AtomicLong原理
它底层使用了CAS的方式,不断比较线程工作内存中的值和主内存中的值是否相等,如果相等的话执行对应原子操作(使用了do…while)
2. LongAdder原理
原理:将AtomicLong中的value值分成一个Cell数组,通过hash算法,对对应位置的Cell进行相应操作,最后将Cell数组的值加起来,再加基础值base获得最终值。
优点是:LongAdder在AtomicLong的基础上将单点的更新压力分散到各个节点,在低并发的时候通过对base的直接更新可以很好的保障和AtomicLong的性能基本保持一致,而在高并发的时候通过分散提高了性能。 相当于从多个线程竞争修改一个value的机会,变成多个线程竞争修改多个value的机会。
缺点是:LongAdder在统计的时候如果有并发更新,可能导致统计的数据有误差。
如果是高并发情况下,优先使用LongAdder,如果是低并发情况下,优先使用AtomicLong更简单一些,如果是序列号生成的话,因为需要使用准备的数值,所以应该使用AtomicLong。
初始时,Cells为null,接着执行CAS更新base的值,如果更新失败,那么就将使用分段操作的逻辑。
如果cs为空或者更新cell结点失败,就会进入longAccumulate()方法。 如果cs不为空并且成功更新对应节点的数据,则返回。
我们将value的值拆分成多个value,比如将100拆分为30, 40, 30,每个value组成一个Cell,整个构成一个Cell数组。
final void longAccumulate(long x, LongBinaryOperator fn,
boolean wasUncontended) {
int h;
if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
Cell[] cs; Cell c; int n; long v;
if ((cs = cells) != null && (n = cs.length) > 0) {
// 如果位置上没有元素
if ((c = cs[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
// cas标志位,防止扩容或者插入元素
if (cellsBusy == 0 && casCellsBusy()) {
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
break done;
}
} finally {
cellsBusy = 0;
}
continue; // Slot is now non-empty
}
}
collide = false;
}
// 该位置已有元素,如果有冲突,标记为true
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
// 更新该位置的值
else if (c.cas(v = c.value,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
break;
// 如果n大于CPU的核数,表示扩容没有意义
else if (n >= NCPU || cells != cs)
collide = false; // At max size or stale
else if (!collide)
collide = true;
// 开始扩容
else if (cellsBusy == 0 && casCellsBusy()) {
try {
if (cells == cs) // Expand table unless stale
cells = Arrays.copyOf(cs, n << 1);
} finally {
cellsBusy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h = advanceProbe(h);
}
// 如果cells为空,那么就初始化
else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
if (cells == cs) {
// 初始化cell的容量为2,将要添加的值放到相应位置
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
break done;
}
} finally {
cellsBusy = 0;
}
}
// Fall back on using base
// 在低并发的时候,使用cas执行add操作(和AtomicLong一样)
else if (casBase(v = base,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
break done;
}
}
将base和Cell数组中所有的元素加起来获取最终的值,如果此时有线程修改Cell元素的值,会导致结果错误。