专栏首页Java编程技术JDK8中新增原子性操作类LongAccumulator

JDK8中新增原子性操作类LongAccumulator

一、 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并发编程基础之并发包源码剖析 一书的出版

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java并发编程之美

    并发编程相比 Java 中其他知识点学习门槛较高,从而导致很多人望而却步。但无论是职场面试,还是高并发/高流量的系统的实现,却都离不开并发编程,于是能够真正掌握...

    加多
  • HttpClient的异步调用,你造?

    HttpClient提供了两种I/O模型:经典的java阻塞I/O模型和基于Java NIO的异步非阻塞事件驱动I/O模型。

    加多
  • 常用开源框架中设计模式使用分析- 装饰器模式(Decorator Pattern)

    装饰器模式是一种结构性模式,它作用是对对象已有功能进行增强,但是不改变原有对象结构。这避免了通过继承方式进行功能扩充导致的类体系臃肿。

    加多
  • LongAccumulator介绍,使用,实现原理

    LongAdder类时LongAccumulator的一个特例,LongAccumulator比LongAdder的功能更强大。例如下面的构造函数,其中accu...

    YanL
  • Tcl中的数学运算

    Tcl中的数学运算,即便是很简单的两个数相加,都要用到命令expr,看下面这个例子。在这个例子中,计算x1与x2之和时通过expr命令实现。可以看到如果直接写{...

    Lauren的FPGA
  • 双指针法:总结篇!

    相信大家已经对双指针法很熟悉了,但是双指针法并不隶属于某一种数据结构,我们在讲解数组,链表,字符串都用到了双指针法,所有有必要针对双指针法做一个总结。

    代码随想录
  • LeetCode 653. 两数之和 IV - 输入 BST(二叉搜索树迭代器&双指针)

    给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。

    Michael阿明
  • FreeRTOS 任务调度 任务切换

    前面文章 < FreeRTOS 任务调度 任务创建 > 介绍了 FreeRTOS 中如何创建任务以及其具体实现。 一般来说, 我们会在程序开始先创建若干个任务...

    orientlu
  • 美团点评2020年测试工程师笔试题

    1.每年的5月17日,美团点评都会在全国各大城市举办517吃货节优惠活动,如果你来负责手机端517某一个活动的测试任务,你会想到从哪些方面测试,来保证517活动...

    ITester软件测试小栈
  • 案例 | 为什么奢侈品牌纷纷押注微信小程序?

    微信推出小程序至今已接近两年,逐渐习惯数字化趋势的奢侈时尚品牌们从最初的观望到全面拥抱并没有耗费太多的时间。

    云蚁cloudant

扫码关注云+社区

领取腾讯云代金券