AtomicLong和LongAdder的比较

1. AtomicLong原理

它底层使用了CAS的方式,不断比较线程工作内存中的值和主内存中的值是否相等,如果相等的话执行对应原子操作(使用了do…while)

2. LongAdder原理

原理:将AtomicLong中的value值分成一个Cell数组,通过hash算法,对对应位置的Cell进行相应操作,最后将Cell数组的值加起来,再加基础值base获得最终值。

优点是:LongAdder在AtomicLong的基础上将单点的更新压力分散到各个节点,在低并发的时候通过对base的直接更新可以很好的保障和AtomicLong的性能基本保持一致,而在高并发的时候通过分散提高了性能。 相当于从多个线程竞争修改一个value的机会,变成多个线程竞争修改多个value的机会。

缺点是:LongAdder在统计的时候如果有并发更新,可能导致统计的数据有误差。

如果是高并发情况下,优先使用LongAdder,如果是低并发情况下,优先使用AtomicLong更简单一些,如果是序列号生成的话,因为需要使用准备的数值,所以应该使用AtomicLong。
在这里插入图片描述
初始时,Cells为null,接着执行CAS更新base的值,如果更新失败,那么就将使用分段操作的逻辑。
如果cs为空或者更新cell结点失败,就会进入longAccumulate()方法。 如果cs不为空并且成功更新对应节点的数据,则返回。
在这里插入图片描述
我们将value的值拆分成多个value,比如将100拆分为30, 40, 30,每个value组成一个Cell,整个构成一个Cell数组。

final void longAccumulate(long x, LongBinaryOperator fn,
                              boolean wasUncontended) {
        int h;
        if ((h = getProbe()) == 0) {
            ThreadLocalRandom.current(); // force initialization
            h = getProbe();
            wasUncontended = true;
        }
        boolean collide = false;                // True if last slot nonempty
        done: for (;;) {
            Cell[] cs; Cell c; int n; long v;
            if ((cs = cells) != null && (n = cs.length) > 0) {
            	// 如果位置上没有元素
                if ((c = cs[(n - 1) & h]) == null) {
                    if (cellsBusy == 0) {       // Try to attach new Cell
                        Cell r = new Cell(x);   // Optimistically create
                        // cas标志位,防止扩容或者插入元素
                        if (cellsBusy == 0 && casCellsBusy()) {
                            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;
                                    break done;
                                }
                            } finally {
                                cellsBusy = 0;
                            }
                            continue;           // Slot is now non-empty
                        }
                    }
                    collide = false;
                }
                // 该位置已有元素,如果有冲突,标记为true
                else if (!wasUncontended)       // CAS already known to fail
                    wasUncontended = true;      // Continue after rehash
                // 更新该位置的值
                else if (c.cas(v = c.value,
                               (fn == null) ? v + x : fn.applyAsLong(v, x)))
                    break;
                // 如果n大于CPU的核数,表示扩容没有意义
                else if (n >= NCPU || cells != cs)
                    collide = false;            // At max size or stale
                else if (!collide)
                    collide = true;
                // 开始扩容
                else if (cellsBusy == 0 && casCellsBusy()) {
                    try {
                        if (cells == cs)        // Expand table unless stale
                            cells = Arrays.copyOf(cs, n << 1);
                    } finally {
                        cellsBusy = 0;
                    }
                    collide = false;
                    continue;                   // Retry with expanded table
                }
                h = advanceProbe(h);
            }
            // 如果cells为空,那么就初始化
            else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
                try {                           // Initialize table
                    if (cells == cs) {
                   		 // 初始化cell的容量为2,将要添加的值放到相应位置
                        Cell[] rs = new Cell[2];
                        rs[h & 1] = new Cell(x);
                        cells = rs;
                        break done;
                    }
                } finally {
                    cellsBusy = 0;
                }
            }
            // Fall back on using base
            // 在低并发的时候,使用cas执行add操作(和AtomicLong一样)
            else if (casBase(v = base,
                             (fn == null) ? v + x : fn.applyAsLong(v, x)))
                break done;
        }
    }

在这里插入图片描述

将base和Cell数组中所有的元素加起来获取最终的值,如果此时有线程修改Cell元素的值,会导致结果错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值