LongAccumulator 源码分析


LongAccumulator

LongAccumulator 能解决什么问题?什么时候使用 LongAccumulator?

1)LongAccumulator 的逻辑和 LongAdder 基本类似,唯一不同的是 LongAccumulator
持有一个函数式接口,目标值是通过该接口计算得到的,相对于 LongAdder,LongAccumulator 更灵活。

如何使用 LongAccumulator?

1)多线程并发更新一个统计值时可以采用 LongAccumulator,如最高同时在线人数。

使用 LongAccumulator 有什么风险?

1)LongAccumulator 使用空间换时间的模式会消耗更多的内存

LongAccumulator 核心操作的实现原理?

创建实例

    /**
     * 二元函数式接口
     */
    private final LongBinaryOperator function;
    /**
     * 身份值
     */
    private final long identity;

    /**
     * 基于一个二元函数式接口和身份值创建 LongAccumulator 实例
     */
    public LongAccumulator(LongBinaryOperator accumulatorFunction,
            long identity) {
        function = accumulatorFunction;
        base = this.identity = identity;
    }

更新值

    /**
     * 使用指定的值 x 更新 LongAccumulator
     */
    public void accumulate(long x) {
        Cell[] cs; long b, v, r; int m; Cell c;
        /**
         * 1)cells 为 null &&
         * 使用函数式接口基于 base 和目标值 x 计算新值不等于 b &&
         * 尝试原子更新 base
         * 2)cells 不为 null
         */
        if ((cs = cells) != null
                || (r = function.applyAsLong(b = base, x)) != b
                && !casBase(b, r)) {
            /**
             * 1)原子更新失败
             * 2)cells 不为 null
             */
            boolean uncontended = true;
            /**
             * 1)cells 为 null,则执行初始化
             * 2)通过线程探测值定位的 cell 为 null,则尝试直接写入值
             * 3)基于 cell 值和目标值 x 计算后的值和旧值不相等 && 原子更新失败,
             * 说明出现 cell 竞争,则需要重新计算并写入值。
             */
            if (cs == null
                    || (m = cs.length - 1) < 0
                    || (c = cs[Striped64.getProbe() & m]) == null
                    || !(uncontended =
                    (r = function.applyAsLong(v = c.value, x)) == v
                    || c.cas(v, r))) {
                longAccumulate(x, function, uncontended);
            }
        }
    }

读取值

    /**
     * 根据函数式接口循环计算新值【参数为累计值和当前 Cell 中的旧值】并返回最终值,
     * 如果计算过程中未发生竞争,则该值是精确的。
     */
    public long get() {
        final Cell[] cs = cells;
        long result = base;
        if (cs != null) {
            for (final Cell c : cs) {
                if (c != null) {
                    result = function.applyAsLong(result, c.value);
                }
            }
        }
        return result;
    }
优质内容筛选与推荐>>
1、深度学习:验证集&测试集区别
2、nodejs与javascript中的aes加密
3、Uber开源深度概率编程语言Pyro,AI实验室蛰伏一年首现身
4、PPGN即插即用GAN:IanGoodfellow推荐的最新模型视频+多图
5、apache工作模式梳理


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号