LongAdder源码阅读笔记

时间:2021-06-12
本文章向大家介绍LongAdder源码阅读笔记,主要包括LongAdder源码阅读笔记使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

功能描述

LongAdder通过创建多个副本对象,解决了多线程使用CAS更新同一个对象造成的CPU阻塞,加快了对线程处理的速度。当多个线程同一时刻更新一个AtomicLong类型的变量时,只有一个线程能够更新成功,其他线程则更新失败,继续尝试更新。

当使用LongAdder类型的变量时,由于副本数组的存在,线程不一定直接更新变量的本身而是更新副本数组,这样多线程请求的对象变多了,从而减少了更新时间,当需要使用变量值时,返回的值是基础变量的值加上数组内每一个副本的值的和。

源码解析

LongAdder继承自Striped64并实现了Serializable接口,而在Striped64类中有一个Cell类

首先分析LongAdder类的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);
    }
}

从上面的代码可以看到LongAdder的实现主要依靠的是cells数组,如果cells数组为空的话,则尝试使用cas更新基础变量base,如果成功了,则add成功,方法结束,如果cas更新base失败了,则证明此时有其他线程参与base变量的更新,此后的处理与cells不为空一致(如果cells不为空,则在此次方法执行前就已经有多线程参与了更新)。
当cells数组不为空或者更新base变量失败后

原文地址:https://www.cnblogs.com/nicholasgub/p/14878596.html