简介

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 VS AtomicLong性能测评帖子

LongAdder的思路

AtomicLong 内部保存着一个 long 类型值,所有的操作都会对这一个值进行操作,而高并发下,就是多个线程争抢这个 long
LongAdder 的思路是将一个值分散到多个数组里面,不同线程命中到数组的不同槽里,各个线程只对自己的槽(哈希得出槽位的)进行CAS操作,这样就将热点分散,冲突概率减小。如果想要获取最终结果,只需要将各个槽里的值加在一起就行了

实现原理

(有空埋,现在时间紧迫~)