前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JDK8中新增原子性操作类LongAccumulator

JDK8中新增原子性操作类LongAccumulator

作者头像
加多
发布2018-09-06 15:04:59
7270
发布2018-09-06 15:04:59
举报
文章被收录于专栏:Java编程技术

一、 LongAccumulator类原理探究

LongAdder类是LongAccumulator的一个特例,LongAccumulator提供了比LongAdder更强大的功能,如下构造函数其中accumulatorFunction一个双目运算器接口,根据输入的两个参数返回一个计算值,identity则是LongAccumulator累加器的初始值。

代码语言:javascript
复制
    public LongAccumulator(LongBinaryOperator accumulatorFunction,
                           long identity) {
        this.function = accumulatorFunction;
        base = this.identity = identity;
    }
代码语言:javascript
复制
public interface LongBinaryOperator {

       //根据两个参数计算返回一个值
       long applyAsLong(long left, long right);
}

LongAdder其实是LongAccumulator的一个特例,调用LongAdder相当使用下面的方式调用LongAccumulator。

代码语言:javascript
复制
LongAdder adder = new LongAdder();
代码语言:javascript
复制
    LongAccumulator accumulator = new LongAccumulator(new LongBinaryOperator() {
        
        @Override
        public long applyAsLong(long left, long right) {
            return left + right;
        }
    }, 0);

LongAccumulator相比于LongAdder可以提供累加器初始非0值,后者只能默认为0,另外前者还可以指定累加规则比如不是累加而是相乘,只需要构造LongAccumulator时候传入自定义双面运算器就OK,后者则内置累加的规则。

从下面代码知道LongAccumulator相比于LongAdder不同在于casBase时候后者传递的是b+x,前者则是调用了r = function.applyAsLong(b = base, x)来计算。

代码语言:javascript
复制
    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);
        }
    }
    
    public void accumulate(long x) {
        Cell[] as; long b, v, r; int m; Cell a;
        if ((as = cells) != null ||
            (r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
            boolean uncontended = true;
            if (as == null || (m = as.length - 1) < 0 ||
                (a = as[getProbe() & m]) == null ||
                !(uncontended =
                  (r = function.applyAsLong(v = a.value, x)) == v ||
                  a.cas(v, r)))
                longAccumulate(x, function, uncontended);
        }
    }

另外前者调用longAccumulate时候传递到是function,而后者是null,从下面代码可知当fn为null时候就是使用v+x加法运算这时候就等价于LongAdder,fn不为null时候则使用传递的fn函数计算,如果fn为加法则等价于LongAdder;

代码语言:javascript
复制
  else if (casBase(v = base, ((fn == null) ? v + x :
                                        fn.applyAsLong(v, x))))
                break;                          // Fall back on using base

更详细的说明敬请期待 Java并发编程基础之并发包源码剖析 一书的出版

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.08.24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、 LongAccumulator类原理探究
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档