LongAdder源码

LongAdder的基本思想就是分散热点,将value值分散到一个Cell数组中,不同线程会命中到数组的不同槽中
各个线程只对自己槽中的值进行CAS操作,最终将各个槽中的变量值累加
Striped64(LongAdder是Striped64的子类)
    static final class Cell{}:内部类
    static final int NCPU:CPU数量,即cells数组的最大长度
    transient volatile Cell[] cells:2的幂次方,方便位运算
    transient volatile long base:基础value值,并发较低时通过CAS更新
    transient volatile int cellsBusy:创建或者扩容cells数组时使用的自旋锁变量调整单元格大小

LongAdder中的increment()

	public void increment() {
		add(1L);
	}

increment()中调用add()

	public void add(long x) {
		Cell[] as; //as表示cells引用
		long b, v; //b表示获取的base值,v表示当前线程hash到的Cell中存储的值
		int m; //m表示cells数组的长度
		Cell a;//a表示当前线程hash到的cell单元格
		//如果(as = cells) != null为true,则表示已扩容
		//如果!casBase(b = base, b + x)为true,则表示CAS操作失败
		if ((as = cells) != null || !casBase(b = base, b + x)) {
			//根据uncontended决定是否扩容
			boolean uncontended = true;
			//判断as == null或(m = as.length - 1) < 0是否为true
			//如果(a = as[getProbe() & m]) == null为true,则表示当前线程所在的Cell为空,需要初始化一个Cell
			//如果!(uncontended = a.cas(v = a.value, v + x))为true,则表示扩容后的槽位CAS操作失败
			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);
		}
	}

add()中调用longAccumulate()

    final void longAccumulate(long x, LongBinaryOperator fn,
                              boolean wasUncontended) {
        //存储线程的hash值
        int h;
        //如果线程的hash值为0,说明未初始化
        if ((h = getProbe()) == 0) {
            //为当前线程计算一个hash值
            ThreadLocalRandom.current(); // force initialization
            //重新获取hash值
            h = getProbe();
            //将wasUncontended改为true,表示不存在竞争
            wasUncontended = true;
        }
        boolean collide = false;                // True if last slot nonempty
        for (;;) {
            Cell[] as; Cell a; int n; long v;
            //cells已经被初始化
            if ((as = cells) != null && (n = as.length) > 0) {
                //如果(a = as[(n - 1) & h]) == null,则表示需要进行初始化
                if ((a = as[(n - 1) & h]) == null) {
                    //判断是否为无锁状态
                    if (cellsBusy == 0) {       // Try to attach new Cell
                        Cell r = new Cell(x);   // Optimistically create
                        //再次判断是否为无锁状态,并将cellsBusy设置为1
                        if (cellsBusy == 0 && casCellsBusy()) {
                            boolean created = false;
                            try {               // Recheck under lock
                                Cell[] rs; int m, j;
                                //初始化
                                if ((rs = cells) != null &&
                                    (m = rs.length) > 0 &&
                                    rs[j = (m - 1) & h] == null) {
                                    rs[j] = r;
                                    created = true;
                                }
                            } finally {
                                cellsBusy = 0;
                            }
                            if (created)
                                break;
                            continue;           // Slot is now non-empty
                        }
                    }
                    collide = false;
                }
                //将wasUncontended改为true,允许重新竞争,执行advanceProbe(h)
                else if (!wasUncontended)       // CAS already known to fail
                    wasUncontended = true;      // Continue after rehash
                //CAS操作成功以后跳出循环
                else if (a.cas(v = a.value, ((fn == null) ? v + x :
                                             fn.applyAsLong(v, x))))
                    break;
                //判断是否大于CPU的核数,如果大于CPU的核数则无需扩容
                else if (n >= NCPU || cells != as)
                    collide = false;            // At max size or stale
                //允许扩容
                else if (!collide)
                    collide = true;
                //判断是否为无锁状态,并将cellsBusy设置为1
                else if (cellsBusy == 0 && casCellsBusy()) {
                    try {
                        //扩容
                        if (cells == as) {      // Expand table unless stale
                            //扩容大小为之前的两倍
                            Cell[] rs = new Cell[n << 1];
                            for (int i = 0; i < n; ++i)
                                //扩容后将之前数组的元素拷贝到新数组中
                                rs[i] = as[i];
                            cells = rs;
                        }
                    } finally {
                        cellsBusy = 0;
                    }
                    collide = false;
                    continue;                   // Retry with expanded table
                }
                h = advanceProbe(h);
            }
            //cells没有加锁且没有初始化,尝试对它进行加锁,并初始化cells数组
            //如果cellsBusy == 0,则表示无锁状态
            //如果cells == as,则表示没有初始化
            //casCellsBusy()将cellsBusy设置为1
            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
                boolean init = false;
                try {                           // Initialize table
                    //再次判断cells == as,则表示没有初始化
                    if (cells == as) {
                        Cell[] rs = new Cell[2];
                        rs[h & 1] = new Cell(x);
                        cells = rs;
                        init = true;
                    }
                } finally {
                    cellsBusy = 0;
                }
                if (init)
                    break;
            }
            //cells正在进行初始化,直接在base上进行累加操作
            else if (casBase(v = base, ((fn == null) ? v + x :
                                        fn.applyAsLong(v, x))))
                break;                          // Fall back on using base
        }
    }

LongAdder中的sum()

	public long sum() {
		Cell[] as = cells; Cell a;
		long sum = base;
		//将Cell数组中的value和base累加作为返回值
		if (as != null) {
			for (int i = 0; i < as.length; ++i) {
				if ((a = as[i]) != null)
					sum += a.value;
			}
		}
		return sum;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值