longadder

多个线程写的时候 竞争多个资源 如竞争到最后一个仍然失败 则执行扩容操作

继承自父类Striped64 中的关键属性

    /** Number of CPUS, to place bound on table size */
    static final int NCPU = Runtime.getRuntime().availableProcessors();

    /**
     * Table of cells. When non-null, size is a power of 2.
     */
    transient volatile Cell[] cells;

    /**
     * Base value, used mainly when there is no contention, but also as
     * a fallback during table initialization races. Updated via CAS.
     */
    transient volatile long base;

    /**
     * Spinlock (locked via CAS) used when resizing and/or creating Cells.
     */
    transient volatile int cellsBusy;

Cell 内部类

    /**
     * Padded variant of AtomicLong supporting only raw accesses plus CAS.
     *
     * JVM intrinsics note: It would be possible to use a release-only
     * form of CAS here, if it were provided.
     */
    @sun.misc.Contended static final class Cell {
    		//一个元素中底层用long存储
        volatile long value;
        Cell(long x) { value = x; }
        final boolean cas(long cmp, long val) {
            return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
        }

        // Unsafe mechanics
        private static final sun.misc.Unsafe UNSAFE;
        private static final long valueOffset;
        static {
            try {
                UNSAFE = sun.misc.Unsafe.getUnsafe();
                Class<?> ak = Cell.class;
                valueOffset = UNSAFE.objectFieldOffset
                    (ak.getDeclaredField("value"));
            } catch (Exception e) {
                throw new Error(e);
            }
        }
    }
    /**
     * Adds the given value.
     *
     * @param x the value to add
     */
    public void add(long x) {
        Cell[] as; long b, v; int m; Cell a;
        //cells  不为null   或   cas 更新base不成功
        if ((as = cells) != null || !casBase(b = base, b + x)) {
            boolean uncontended = true;
            //  如果cells 为null  或  cells长度<=0  或  线程的探测值所对应 cells的位置 为null  或  cas 线程的探测值所对应 cells的位置的值  失败
            if (as == null || (m = as.length - 1) < 0 ||
                (a = as[getProbe() & m]) == null ||
                !(uncontended = a.cas(v = a.value, v + x)))  //赋值uncontended = false
                longAccumulate(x, null, uncontended);        //执行父类longAccumulate  核心逻辑  参数  value,null,false
        }
    }

longAccumulate(value,null,false):

/**
     * Handles cases of updates involving initialization, resizing,
     * creating new Cells, and/or contention. See above for
     * explanation. This method suffers the usual non-modularity
     * problems of optimistic retry code, relying on rechecked sets of
     * reads.
     *
     * @param x the value
     * @param fn the update function, or null for add (this convention
     * avoids the need for an extra field or function in LongAdder).
     * @param wasUncontended false if CAS failed before call
     */
    final void longAccumulate(long x, LongBinaryOperator fn,
                              boolean wasUncontended) {
        int h;
        //如果当前线程的Thread.threadLocalRandomProbe is zero
        if ((h = getProbe()) == 0) {
            //强制初始化
            ThreadLocalRandom.current(); // force initialization
            h = getProbe();
            wasUncontended = true;
        }
        //  最后的槽不为空  则为true   用于扩容,false 重试
        boolean collide = false;                // True if last slot nonempty
        for (;;) {
            Cell[] as; Cell a; int n; long v;
            // 如果槽容器已经初始化
            if ((as = cells) != null && (n = as.length) > 0) {
            		当前线程 所路由的槽 为null
                if ((a = as[(n - 1) & h]) == null) {
                    /** 
 										* 自旋锁,通过CAS操作加锁,用于保护创建或者扩展Cell表。
                    * 无其他线程扩容   执行扩容
										*/  
                    if (cellsBusy == 0) {       // Try to attach new Cell
                        //先创建自己需要的cell
                        Cell r = new Cell(x);   // Optimistically create
                        // 如果锁仍然空闲 且cas获取成功
                        if (cellsBusy == 0 && casCellsBusy()) {
                            boolean created = false;
                            try {               // Recheck under lock
                                Cell[] rs; int m, j;
                                // 再次检查 当前线程 所路由的槽 为null
                                if ((rs = cells) != null &&
                                    (m = rs.length) > 0 &&
                                    rs[j = (m - 1) & h] == null) {
                                    //设置该槽对应的cell
                                    rs[j] = r;
                                    //创建成功标志
                                    created = true;
                                }
                            } finally {
                                //最终保证 锁被释放
                                cellsBusy = 0;
                            }
                            //创建成功  跳出循环
                            if (created)
                                break;
                            continue;           // Slot is now non-empty
                        }
                    }
                    //锁被占用 有冲突 继续重试  
                    collide = false;
                }
                else if (!wasUncontended)       // CAS already known to fail   已知cas抢占槽失败
                    wasUncontended = true;      // Continue after rehash       重散列后继续下次抢占
                else if (a.cas(v = a.value, ((fn == null) ? v + x :
                                             fn.applyAsLong(v, x))))  //cas更新槽
                    break;  //成功结束
                else if (n >= NCPU || cells != as)  //槽数目大于服务器核数  或 容器扩容了 有冲突 不让再执行到扩容了 重试循环
                    collide = false;            // At max size or stale   
                else if (!collide)                  //之前无冲突  设置为无冲突
                    collide = true;
                else if (cellsBusy == 0 && casCellsBusy()) {  //cas获取锁成功
                    try {
                        //如果as与cells指向同一对象  说明之前未扩容  执行扩容
                        if (cells == as) {      // Expand table unless stale
                            Cell[] rs = new Cell[n << 1];  //扩容为2倍
                            for (int i = 0; i < n; ++i)
                                rs[i] = as[i];             //旧槽copy
                            cells = rs;                    //更新容器
                        }
                    } finally {
                        cellsBusy = 0;   //释放锁
                    }
                    collide = false;   //设置为无冲突
                    continue;                   // Retry with expanded table
                }
                h = advanceProbe(h);  //线程值变化  (不一直竞争同一个槽)
            }
            //获取锁
            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
            		//初始化容器
                boolean init = false;
                try {                           // Initialize table
                    if (cells == as) {
                        Cell[] rs = new Cell[2];  //初始值为2
                        rs[h & 1] = new Cell(x);  // 创建当前线程的槽对象
                        cells = rs;               //更新槽
                        init = true;
                    }
                } finally {
                    cellsBusy = 0;  //释放锁 
                }
                if (init)
                    break;   //初始化成功  结束
            }
            //尝试cas更新base成功  结束
            else if (casBase(v = base, ((fn == null) ? v + x :
                                        fn.applyAsLong(v, x))))
                break;                          // Fall back on using base
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值