AtomicLong和LongAdder:
为什么要引入LongAdder:
AtomicLong底层是采用CAS,在高并发下,会出现大量失败并不断自旋,这比较耗性能。LongAdder就是为了解决这个问题。
LongAdder原理:
比如有三个ThreadA、ThreadB、ThreadC,每个线程对value增加10。
对于AtomicLong,最终结果的计算始终是下面这个形式:value=10+10+10=30。多个线程执行累加时,都是串行进行的。
但是对于LongAdder来说,内部有一个base变量,一个Cell[]数组。
base变量:非竞态条件下,直接累加到该变量上。
Cell[]数组:竞态条件下,累加个各个线程自己的槽Cell[i]中,Unsafe来CAS操作。
最终结果的计算是下面这个形式:
这个方法只能得到某个时刻的近似值,这也就是LongAdder并不能完全替代LongAtomic的原因之一。因为此时是对cell中的value直接累加,就会出现一个线程在设置value值时,执行到了一半,但未完成写操作,此时其他线程就已执行完读操作,因此是一个近似值。
CAS是sun.misc.Unsafe中提供的操作,只对int、long、对象类型(引用或者指针)提供了这种操作,其他类型都需要转化为这三种类型才能进行CAS操作。