美文网首页并发编程互联网科技程序员
JDK8中新增原子性操作类LongAccumulator

JDK8中新增原子性操作类LongAccumulator

作者: 阿里加多 | 来源:发表于2017-08-24 18:35 被阅读442次

一、 LongAccumulator类原理探究

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

    public LongAccumulator(LongBinaryOperator accumulatorFunction,
                           long identity) {
        this.function = accumulatorFunction;
        base = this.identity = identity;
    }
public interface LongBinaryOperator {

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

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

LongAdder adder = new LongAdder();
    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)来计算。


    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;

  else if (casBase(v = base, ((fn == null) ? v + x :
                                        fn.applyAsLong(v, x))))
                break;                          // Fall back on using base

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

相关文章

网友评论

    本文标题:JDK8中新增原子性操作类LongAccumulator

    本文链接:https://www.haomeiwen.com/subject/uagedxtx.html