请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

LongAdder

LongAdder会将数据分离成一个数组,每个线程访问时通过hash等算法映射到数组其中一个数字进行计数,计数的最终结果是这个数组的求和累加,这个过程具体是怎样的?数组里每个元素都是这个数据吗?如果有hash冲突怎么办?

正在回答 回答被采纳积分+3

2回答

Jimin 2018-12-28 00:20:31

// 返回累加的和,也就是“当前时刻”的计数值



 // 此返回值可能不是绝对准确的,因为调用这个方法时还有其他线程可能正在进行计数累加,



 // 方法的返回时刻和调用时刻不是同一个点,在有并发的情况下,这个值只是近似准确的计数值



 // 高并发时,除非全局加锁,否则得不到程序运行中某个时刻绝对准确的值,但是全局加锁在高并发情况下是下下策



 // 在很多的并发场景中,计数操作并不是核心,这种情况下允许计数器的值出现一点偏差,此时可以使用LongAdder



 // 在必须依赖准确计数值的场景中,应该自己处理而不是使用通用的类



 public long sum() {



 Cell[] as = cells; Cell a;



 long sum = base;



 if (as != null) {



 for (int i = 0; i < as.length; ++i) {



 if ((a = as[i]) != null)



 sum += a.value;



 }



 }



 return sum;



 }

0 回复 有任何疑惑可以回复我~
Jimin 2018-12-25 23:12:51

你好,这个问题更适合从源码上去分析,推荐一篇文章,对这个类的源码做了比较详细的讲解,https://blog.csdn.net/u011392897/article/details/60480108 ,你先看下,看看对源码的分析是否可以满足你的需求,如果哪里不懂,继续这里回复即可。

0 回复 有任何疑惑可以回复我~
  • 提问者 红邮筒 #1
    看完了,看的很吃力,不知道理解的对不对,麻烦老师纠正:
    LongAdder提供一个元素为cell的数组,每个线程映射到一个cell,也就是使用这个cell作为计数器,cell计数器初始为0,在这个cell里进行加1或减1操作,最后把所有cell的值和base(在本例子中为0)相加得到count的值。
    因为会扩容,所以不会有hash冲突,直到数组大小为CPU的核数,不能再继续扩容,这时候怎么办呢?没看明白
    回复 有任何疑惑可以回复我~ 2018-12-27 09:59:10
  • 提问者 红邮筒 #2
    还有,老师您说:“LongAdder在统计的时候如果有并发更新,可能会导致统计的数据有误差”,这里的“统计”是不是指在最后把所有cell的值和base相加?这个时候不是已经执行完毕,怎么还会有并发更新呢?
    回复 有任何疑惑可以回复我~ 2018-12-27 10:05:20
  • Jimin 回复 提问者 红邮筒 #3
    不是cpu核数,2^n个,类似于jdk8以前的concurrentHashmap的扩容
    回复 有任何疑惑可以回复我~ 2018-12-28 00:18:48
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信