zoukankan      html  css  js  c++  java
  • 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;
        }
    
  • 相关阅读:
    【Vue】 修饰符sync
    【VUE】vue路由跳转的方式
    【Element】elementui的Cascader 级联选择器,在懒加载的时候数据无法回显的解决方案
    【ES6】利用ES6 Set 将数组去重
    【.NETCORE】Refit 框架
    【.NETCORE】ASP.NET Core SignalR
    【Visual Studio Code】驼峰翻译助手
    VueX(Vue状态管理模式)
    hdmi 随笔
    ad 差分布线 等长布线
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10055558.html
Copyright © 2011-2022 走看看