深入剖析LongAdder
LongAdder是JDK8添加到JUC中的。它是一个线程安全的、比Atomic*系工具性能更好的"计数器"。
它提供的方法主要有下面这些:
1|00 LongAdder的类图
LongAdder本身没有成员变量,其值的变更实际上是由父类Striped64管理的。
Striped64通过两个成员变量来管理value,分别是base和cells,cells是一个数组,其元素是Striped64的内部类Cell的实现,Cell很简单,只记录一个value。
当LongAdder不存在并发访问的时候,会直接通过cas的方式更新base的值,存在并发访问时,会定位到某一个cell,修改cell的value。
最终,value = base + sum(cells)。
2|01 深挖add方法
add方法的作用是将当前的value值 + x。其实弄懂add方法后,increment方法和decrement自然就明白了,这两个方法里面调的其实就是add方法。
2|11.1 add方法的实现
初始状态下,cells==null,所以#1代码中,第一个条件一定是false,此时会通过casBase方法,以CAS的方式更新base值,且只有当cas失败时,才会走到if中。
啥时候会失败呢?存在竞争的时候。由此可以看出,当不存在竞争的时候,LongAdder是通过累加base值实现value的更新的。
当存在竞争的时候,LongAdder会尝试定位到其中的一个Cell,通过更新这个Cell的值来维护整体的value。这个过程如下:
cells==null时的处理在注释中已经标出。cellsBusy是用来控制并发修改cells的变量,初始值为0,通过casCellsBusy将cellsBusy的值从0更新为1。
然后,new了一个初始大小为2的Cell数组,new了一个Cell并将add的值作为初始值,然后计算一个cells的index,将这个Cell赋值进去。
最后,更新实例变量cells,并将cellsBusy重置为0。
cells!=null时,处理如下:
过程如下:
2|21.2 它为啥比AtomicLong更加高效
以AtomicLong的getAndAdd方法做一下对比。下面是这个方法的源码:
AtomicLong的实现是通过无限循环cas的方式更新当前维护的值,可以想象,在并发足够大的情况下,cas的失败率会很高,这里循环次数剧增,造成CPU使用率飙高。
通过上文分析LongAdder.add(int x)的原理,LongAdder先尝试一次cas更新,如果失败会转而通过Cell[]的方式更新值,如果计算index的方式足够散列,那么在并发量大的情况下,多个线程定位到同一个cell的概率也就越低,这有点类似于分段锁的意思。
由此也可以分析出另一点,在并发量不大的情况下,二者的性能是没有多大差异的。
3|02 深挖sum方法
sum方法用于返回LongAdder当前的值。
3|12.1 sum方法的实现
sum方法的实现很简单,其实就是 base + sum(cells)。源码如下:
3|22.2 为啥在并发情况下sum的值不精确
由上述源码可以发现,sum执行时,并没有限制对base和cells的更新。也就是说,对LongAdder的最后一次更新not happens-before 最近的一次读取。
首先,最终返回的sum局部变量,初始被复制为base,而最终返回时,很可能base已经被更新了,而此时局部变量sum不会更新,造成不一致。
其次,这里对cell的读取也无法保证是最后一次写入的值。
所以,sum方法在没有并发的情况下,可以获得正确的结果。
4|03 深挖reset方法
用于初始化base和cells数组,将值重置为0。
4|13.1 reset方法的实现
源码如下:
其实就是将base和cells数组挨个设置成0。
4|23.2 为啥不可以在并发情况下使用
因为reset方法并不是原子操作,它先将base重置成0,假设此时CPU切走执行sum,此时的sum就变成了减去base后的值。
也就是说,在并发量大的情况下,执行完此方法并不能保证其他线程看到的是重置后的结果。所以要慎用。
5|04 总结
在实际工作中,可根据LongAdder和AtomicLong的特点来使用这两个工具。
当需要在高并发下有较好的性能表现,且对值的精确度要求不高时,可以使用LongAdder(例如网站访问人数计数)。
当需要保证线程安全,可允许一些性能损耗,要求高精度时,可以使用AtomicLong。
参考链接:深入剖析LongAdder是咋干活的
__EOF__
作 者:HKnight
出 处:https://www.cnblogs.com/HKnight/p/16588963.html
关于博主:编程路上的小学生,热爱技术,喜欢专研。评论和私信会在第一时间回复。或者直接私信我。
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异