比AtomicLong更高效的并发计数类LongAdder

最近在看https://github.com/alibaba/Sentinel(轻量级的流量控制、熔断降级 Java 库)源码的时候,看到在统计数量的时候使用了LongAdder。这个LongAdder是jdk1.8新增的,出自Doug Lea之手,伟大的Java并发大师的鼻祖。在没有接触到LongAdder之前,AtomicLong这个类在并发计数上无论性能还是准确性已经做得极好了。在阿里流控框架中使用这样一个LongAdder类,必然有其过人之处。

回顾AtomicLong

AtomicLong是通过CAS(即Compare And Swap)原理来完成原子递增递减操作,在并发情况下不会出现线程不安全结果。AtomicLong中的value是使用volatile修饰,并发下各个线程对value最新值均可见。我们以incrementAndGet()方法来深入。

 	 public final long incrementAndGet() {
   
        return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
    }

这里是调用了unsafe的方法

    public final long getAndAddLong(Object var1, long var2, long var4) {
   
        long var6;
        do {
   
            var6 = this.getLongVolatile(var1, var2);
        } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

        return var6;
    }

方法中this.compareAndSwapLong()有4个参数,var1是需要修改的类对象,var2是需要修改的字段的内存地址,var6是修改前字段的值,var6+var4是修改后字段的值。compareAndSwapLong只有该字段实际值和var6值相当的时候,才可以成功设置其为var6+var4。

multiple-thread-cas-show1

再继续往深一层去看

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

这里Unsafe.compareAndSwapLong是native方法,底层通过JNI(Java Native Interface)来完成调用,实际就是借助C来调用CPU指令来完成。

实现中使用了do-while循环,如果CAS失败,则会继续重试,直到成功为止。并发特别高的时候,虽然这里可能会有很多次循环,但是还是可以保证线程安全的。不过如果自旋CAS操作长时间不成功,竞争较大,会带CPU带来极大的开销,占用更多的执行资源,可能会影响其他主业务的计算等。

LongAdder怎么优化AtomicLong

Doug Lea在jdk1.5的时候就针对HashMap进行了线程安全和并发性能的优化,推出了分段锁实现的ConcurrentHashMap。一般Java面试,基本上离不开ConcurrentHashMap这个网红问题。另外在ForkJoinPool中,Doug Lea在其工作窃取算法上对WorkQueue使用了细粒度锁来较少并发的竞争,更多细节可参考我的原创文章ForkJoin使用和原理剖析。如果已经对ConcurrentHashMap有了较为深刻的理解,那么现在来看LongAdder的实现就会相对简单了。

来看LongAdder的increase()方法实现,

    public void add(long x) {
   
        Cell[] as; long b, v; int m; Cell a;
        //第一个if进行了两个判断,(1)如果cells不为空,则直接进入第二个if语句中。(2)同样会先使用cas指令来尝试add,如果成功则直接返回。如果失败则说明存在竞争,需要重新add
        if ((as = cells) != null || !casBase(b = base, b + x)) {
   
            boolean uncontended = true;
            if (as == null || (m = as.length - 1) < 0 ||
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值