LongAdder及AtomicLong
AtomicLong原理
就像我们所知道的那样,AtomicLong的原理是依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目的。那么LongAdder又是使用到了什么原理?难道有比cas更加快速的方式?
LongAdder原理
这里让我困惑的一个问题是LongAdder中没有类似于AtomicLong中getAndIncrement()或者incrementAndGet()这样的原子操作,所以只能通过increment()方法和longValue()方法的组合来实现更新和获取的动作,然而这样不能保证这个组合操作的原子性,猜想也许LongAdder就是不具备这样的机制吧。那么就主要看一下increment()和longValue()方法。
increment方法:
分析increment()方法,可以看到该方法就是对add(long x)的封装,那么具体来分析一下这个方法
public void add(long x) {Cell[] as; long b, v; int m; Cell a;if ((as = cells) != null || !casBase(b = base, b + x)) {boolean uncontended = true;if (as == null || (m = as.length - 1) < 0 ||(a = as[getProbe() & m]) == null ||!(uncontended = a.cas(v = a.value, v + x)))longAccumulate(x, null, uncontended);}}
这里重点是casBase(b = base, b + x),来看一下它做了什么
final boolean casBase(long cmp, long val) {return UNSAFE.compareAndSwapLong(this, BASE, cmp, val);}
这里的四个条件其实并不是并列的,而是递进式的,1和2判断cells数组是否为空,3取cells数组中的任意一个元素a判断是否为空,4是对a进行cas操作并将执行结果赋值标志位uncontended。从这里可以给出第二个结论,当竞争激烈到一定程度无法对base进行累加操作时,会对cells数组中某个元素进行更新。
最后来看一下当上述条件无法全部满足时调用的longAccumulate(x, null, uncontended)方法
final void longAccumulate(long x, LongBinaryOperator fn,boolean wasUncontended) {int h;if ((h = getProbe()) == 0) {ThreadLocalRandom.current(); // force initializationh = getProbe(); //返回当前线程的threadLocalRandomProbe值wasUncontended = true;}boolean collide = false; // True if last slot nonemptyfor (;;) {Cell[] as; Cell a; int n; long v;if ((as = cells) != null && (n = as.length) > 0) {if ((a = as[(n - 1) & h]) == null) {if (cellsBusy == 0) { // cells数组中对应位置没有数据则插入新对象Cell r = new Cell(x); if (cellsBusy == 0 && casCellsBusy()) {boolean created = false;try { // Recheck under lockCell[] rs; int m, j;if ((rs = cells) != null &&(m = rs.length) > 0 &&rs[j = (m - 1) & h] == null) {rs[j] = r;created = true;}} finally {cellsBusy = 0;}if (created)break;continue; // Slot is now non-empty}}collide = false;}else if (!wasUncontended) // CAS already known to failwasUncontended = true; // Continue after rehashelse if (a.cas(v = a.value, ((fn == null) ? v + x :fn.applyAsLong(v, x)))) //对该位置的cell元素进行累加break;else if (n >= NCPU || cells != as)collide = false; // At max size or stale //判断数组大小是否大于核数else if (!collide)collide = true;else if (cellsBusy == 0 && casCellsBusy()) { //对cells数组进行扩容,直接扩容为2倍try {if (cells == as) { // Expand table unless staleCell[] rs = new Cell[n << 1];for (int i = 0; i < n; ++i)rs[i] = as[i];cells = rs;}} finally {cellsBusy = 0;}collide = false;continue; // Retry with expanded table}h = advanceProbe(h);}else if (cellsBusy == 0 && cells == as && casCellsBusy()) { //cellsBusy这里是做为一个自旋锁来使用的boolean init = false;try { // 初始化cells数组大小为2if (cells == as) {Cell[] rs = new Cell[2];rs[h & 1] = new Cell(x);cells = rs;init = true;}} finally {cellsBusy = 0;}if (init)break;}else if (casBase(v = base, ((fn == null) ? v + x :fn.applyAsLong(v, x)))) //对base进行CAS操作break; // Fall back on using base}}
这个方法比较长,大致对几个关键点做了注释,该方法主要是用一个死循环对cells数组中的元素进行操作,当要更新的位置的元素为空时插入新的cell元素,否则在该位置进行CAS的累加操作,如果CAS操作失败并且数组大小没有超过核数就扩容cells数组。
总结
LongAdder类与AtomicLong类的区别在于高并发时前者将对单一变量的CAS操作分散为对数组cells中多个元素的CAS操作,取值时进行求和;而在并发较低时仅对base变量进行CAS操作,与AtomicLong类原理相同。不得不说这种分布式的设计还是很巧妙的。
LongAdder及AtomicLong相关推荐
- 性能优化之使用LongAdder替换AtomicLong
欢迎关注方志朋的博客,回复"666"获面试宝典 来源:https://juejin.cn/post/6921595303460241415 写在前面 本篇文章并不会直接进入主题讲为 ...
- [JDK8]性能优化之使用LongAdder替换AtomicLong
如果让你实现一个计数器,有点经验的同学可以很快的想到使用AtomicInteger或者AtomicLong进行简单的封装. 因为计数器操作涉及到内存的可见性和线程之间的竞争,而Atomic***的实现 ...
- Java中的LongAdder和AtomicLong有什么区别?
● Java中的LongAdder和AtomicLong有什么区别? 考点:JDK 参考回答: JDK1.8引入了LongAdder类.CAS机制就是,在一个死循环内,不断尝试修改目标值,直到修改成功 ...
- LongAdder和AtomicLong哪个性能更好,为什么?
点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/limenghua9112/ article/details/107950744 概述 AtomicLong是作者Doug Le ...
- 【078期】java.util.* 并发包下 LongAdder 和 AtomicLong 哪个性能更好,为什么?
点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方留言必回,有问必答! 每天 08:00 更新文章,每天进步一点点... 概述 ...
- LongAdder和AtomicLong
LongAdder AmoticLong AtomicLong是作用是对长整形进行原子操作. 原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束. 在32位操作系统中,64位 ...
- LongAdder 和 AtomicLong
有幸看到一篇关于这个讲解 2个类的讲解,自己也归纳总结一下. 一.解析 看源码底层会发现实现机制不一样,当然这个也是必须的 LongAdder 点进去之后会发现,CAS 它是一个CAS的实现类.至于C ...
- AtomicLong和LongAdder的区别
转载自 https://blog.csdn.net/yao123long/article/details/63683991 前言 最近在看到不少框架里面使用到了LongAdder这个类,而并非At ...
- 线程安全之原子性Atomic(AtomicInteger|LongAdder|AtomicLong)
线程安全性 当多线程访问某个类时,不管运行环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何的同步或者协同,这个类都能表现出正确的行为,那么这个类就是线程安全的. 原子性 提供 ...
最新文章
- html滑动逐渐覆盖效果,创意jQuery和CSS3滑动覆盖响应式幻灯片特效
- 从零开始一起学习SLAM | 为啥需要李群与李代数?
- Spring - 同一个类中的方法互相调用,注解失效问题的分析和解决(转)
- Hadoop教程(三):HDFS、MapReduce、程序入门实践
- vue - blog开发学习6
- 无线路由器和计算机怎么连接网络连接,华为无线路由器怎么连接宽带上网
- python输出日期语句_如何从Python的原始语句中提取时间-日期-时间段信息
- NO4 findmv--特殊符号..和.
- 长城汽车:魏牌宣布涨价 咖啡系部分车型上调5000-12000元
- python海龟作图不用循环_10分钟,利用聪明的小海龟可以制作出绚丽的视觉效果,你信不信呢...
- java 云 代码_我 - java代码库 - 云代码
- 推荐几款连字字体,在代码编辑器中启用连字字体(Visual Studio Code)
- 程序猿财务自由之路·规划篇
- windows11修改开机密码为空解决方案
- 移动医疗是什么 移动医疗应用实例
- LQ0141 纸张尺寸【水题】
- 韩顺平-linux笔记
- 马云唱京剧《空城计》,柳传志说相声:“商界春晚”大佬们真会玩(附视频)...
- 怎样让chatGPT给你打工然后月入过千?
- Orcale语句大全
热门文章
- python错误2503_Win10卸载python总是提示error2503失败各种解决办法
- 2022灵活用工十大新趋势!
- php操作redis(list)队列操作
- 手机租赁是风口吗?这家公司试推期间日单249
- 一个Python写的视频剪辑软件,好用!
- 什么是Mobsync.exe,为什么运行?
- mysql数据库连表查询的几种方法
- 安卓手机卡顿怎么解决_安卓手机卡顿的问题,终于解决了
- (2021-07-14~)“kuangbin带你飞”专题计划——专题十三:基础计算几何
- ssh中前后台的数据交互