文档章节

比LongAddr功能更强大的LongAccumulator原子类原理探究

须臾之余
 须臾之余
发布于 07/17 21:11
字数 709
阅读 18
收藏 0

面试题

(1)LongAccumulator与LongAddr类的结构

(2)LongAddr与LongAccumulator类有什么区别?

(3)LongAddr与LongAccumulator类相同点?

(1)LongAccumulator与LongAddr类的结构

(2)LongAddr与LongAccumulator类有什么区别?

LongAccumulator类原理分析

/**
 * Creates a new instance using the given accumulator function
 * and identity element.
 * @param accumulatorFunction a side-effect-free function of two arguments
 * @param identity identity (initial value) for the accumulator function
 */
public LongAccumulator(LongBinaryOperator accumulatorFunction,
                       long identity) {
    this.function = accumulatorFunction;
    base = this.identity = identity;
}
@FunctionalInterface
public interface LongBinaryOperator {

    /**
     * Applies this operator to the given operands.
     *
     * @param left the first operand
     * @param right the second operand
     * @return the operator result
     */
    //根据两个参数计算并返回一个值
    long applyAsLong(long left, long right);
}

首先LongAccumulator类相比于LongAddr功能更加强大,如上代码accumulatorFunction是一个双目运算器接口,其根据输入的两个参数返回一个计算值,identity则是LongAccumulator累加器的初始值。

如何使用LongAccumulator

LongAdder longAdder = new LongAdder();
new LongAccumulator(new LongBinaryOperator() {
    @Override
    public long applyAsLong(long left, long right) {
        return left+right;
    }
},0);

LongAccumulator相比于LongAdder,可以为累加器提供非0的初始值,而LongAdder只能提供默认的0值。

另外,LongAccumulator还可以指定累加规则,比如累加或者相乘,只需要在构造LongAccumulator时,传入自定义的双目运算器即可,后者则内置累加规则。

LongAddr的add方法

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);
    }
}

LongAccumulator的accumulate方法

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);
    }
}

从上面两段代码可知,LongAccumulator相比于LongAddr不同之处在于调用casBase时;

LongAccumulator使用 r = function.applyAsLong(b = base, x)来计算

LongAddr使用casBase(b = base, b + x)来计算

另外,LongAccumulator在调用 longAccumulate 时传递的是 function ,而LongAddr传递的是null。

final void longAccumulate(long x, LongBinaryOperator fn,
                          boolean wasUncontended) {
  ....
        else if (casBase(v = base, ((fn == null) ? v + x :
                                    fn.applyAsLong(v, x))))
            break;                          // Fall back on using base
    }
}

通过LongAccumulator和LongAddr的longAccumulate()方法可知:当fn为null时就使用v+x加法运算,这时候就等价于LongAddr,当fn不为null时,则使用传递的fn函数计算。

(3)LongAddr与LongAccumulator类相同点?

LongAddr与LongAccumulator类都是使用非阻塞算法CAS实现的,这相比于使用锁实现原子性操作在性能上有很大的提高。

LongAddr类是LongAccumulator类的一个特例,只是LongAccumulator提供了更强大的功能,可以让用户自定义累加规则。

参考书籍:

Java并发编程之美

 

© 著作权归作者所有

须臾之余
粉丝 119
博文 60
码字总数 161645
作品 0
吉安
程序员
私信 提问
JDK8中新增原子性操作类LongAccumulator

一、 LongAccumulator类原理探究 LongAdder类是LongAccumulator的一个特例,LongAccumulator提供了比LongAdder更强大的功能,如下构造函数其中accumulatorFunction一个双目运算器接口,根据输...

今天你不奋斗明天你就落后
2017/08/24
0
0
Java并发学习(十一)-LongAdder和LongAccumulator探究

Java8在atomic包新增了5个类,分别是,,,,。其中,Sriped64作为父类,其他分别是long和double的具体实现。 下面首先从父类这个类开始讲,其几个类都是遵从它的结构进行实现的。 What is ...

anLA_
2017/11/30
0
0
4、并发增强

4.1 概述 这部分用的不多,仅简单记录一下新特性 4.2 原子值 4.2.1 更新方法 Java 8 增加了两个新方法 updateAndGet 和 accumulateAndGet 用于更新原子类的值,取代老API的循环方式。 4.2.2 ...

苗新国
2016/06/22
85
0
UITableView 子类--XFSettings

使用 UITableViewController 为基类,用于快速构建设置界面,可定制性强,有多个 cell 类型缓存重用,扩展性强,可继承 XFSettingCell 或功能更强大的 XFSettingInfoCell 作为父类进行自定义...

yizzuide
2015/08/22
841
0
KVO探究(二)---原理篇

一、查看对象的观察信息observationInfo 代码如下: 通过runtime再做进一步的分析,发现观察的信息是一个私有类NSKeyValueObservationInfo,该类中有一个数组的变量(注意不是属性)_observ...

大鹏鸟
2017/12/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring boot 静态资源访问

0. 两个配置 spring.mvc.static-path-patternspring.resources.static-locations 1. application中需要先行的两个配置项 1.1 spring.mvc.static-path-pattern 这个配置项是告诉springboo......

moon888
今天
3
0
hash slot(虚拟桶)

在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小。 round robin算法:是把数据mod后直接映射...

李朝强
今天
4
0
Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
今天
19
0
java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
今天
9
0
太全了|万字详解Docker架构原理、功能及使用

一、简介 1、了解Docker的前生LXC LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpa...

Java技术剑
今天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部