简介
JDK8里在 java.util.concurrent.atomic
包里引入了一个新原子类—— LongAdder
。该类相比 AtomicLong
在高并发下有更好的表现,但是它消耗的内存空间也会比 AtomicLong
多。
Under low update contention, the two classes have similar characteristics. But under high contention, expected throughput of this class is significantly higher, at the expense of higher space consumption.
三分钟学吹牛
- Q:为什么还要增加
LongAdder
这个工具,AtomicLong
在高并发下有什么问题吗 - Q:并发数低时,可以用
LongAdder
替代AtomicLong
吗 - Q:高并发下
LongAdder
为什么比AtomicLong
表现更好
为什么引入LongAdder
因为 AtomicLong
在底层使用的是自旋锁,在并发量低的时,线程冲突的概率比较小,自旋的线程数量不会多,消耗的CPU资源不会多;而并发量高了,N个线程执行CAS操作失败进入自旋,就会很占CPU资源。所以自旋是 AtomicLong
的瓶颈。所以 LongAdder
就是为了解决 AtomicLong
在高并发下自旋锁的瓶颈问题。
LongAdder可以替代AtomicLong吗
要看何种业务场景。
从功能上考虑, AtomicLong
提供的功能相对更加丰富,不仅能做自增/自减,还能递增并获取、获取并递增等等;而 LongAdder
的功能相对单薄一些,它基本就只做递增/递减的操作,最后的结果值还需要精确同步后才能获取。
从空间上考虑, LongAdder
采用了空间换时间的策略,相对来说更耗空间资源。
总之,并发量少的时候使用 AtomicLong
即可,如果并发量高,存在写多读少的情况,可以考虑 LongAdder
LongAdder的思路
AtomicLong
内部保存着一个 long
类型值,所有的操作都会对这一个值进行操作,而高并发下,就是多个线程争抢这个 long
值LongAdder
的思路是将一个值分散到多个数组里面,不同线程命中到数组的不同槽里,各个线程只对自己的槽(哈希得出槽位的)进行CAS操作,这样就将热点分散,冲突概率减小。如果想要获取最终结果,只需要将各个槽里的值加在一起就行了
实现原理
(有空埋,现在时间紧迫~)