专栏首页Java编程技术JDK8中新增原子性操作类LongAdder

JDK8中新增原子性操作类LongAdder

LongAdder简单介绍

LongAdder类似于AtomicLong是原子性递增或者递减类,AtomicLong已经通过CAS提供了非阻塞的原子性操作,相比使用阻塞算法的同步器来说性能已经很好了,但是JDK开发组并不满足,因为在非常高的并发请求下AtomicLong的性能不能让他们接受,虽然AtomicLong使用CAS但是CAS失败后还是通过无限循环的自旋锁不断尝试的

    public final long incrementAndGet() {
        for (;;) {
            long current = get();
            long next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

在高并发下N多线程同时去操作一个变量会造成大量线程CAS失败然后处于自旋状态,这大大浪费了cpu资源,降低了并发性。那么既然AtomicLong性能由于过多线程同时去竞争一个变量的更新而降低的,那么如果把一个变量分解为多个变量,让同样多的线程去竞争多个资源那么性能问题不就解决了?是的,JDK8提供的LongAdder就是这个思路。下面通过图形来标示两者不同。

image.png

如图AtomicLong是多个线程同时竞争同一个变量。

image.png

如图LongAdder则是内部维护多个变量,每个变量初始化都0,在同等并发量的情况下,争夺单个变量的线程量会减少这是变相的减少了争夺共享资源的并发量,另外多个线程在争夺同一个原子变量时候如果失败并不是自旋CAS重试,而是尝试获取其他原子变量的锁,最后获取当前值时候是把所有变量的值累加后返回的。

LongAdder维护了一个延迟初始化的原子性更新数组和一个基值变量base.数组的大小保持是2的N次方大小,数组表的下标使用每个线程的hashcode值的掩码表示,数组里面的变量实体是Cell类型,Cell类型是AtomicLong的一个改进,用来减少缓存的争用,对于大多数原子操作字节填充是浪费的,因为原子性操作都是无规律的分散在内存中进行的,多个原子性操作彼此之间是没有接触的,但是原子性数组元素彼此相邻存放将能经常共享缓存行,所以这在性能上是一个提升。

另外由于Cells占用内存是相对比较大的,所以一开始并不创建,而是在需要时候在创建,也就是惰性加载,当一开始没有空间时候,所有的更新都是操作base变量,

自旋锁cellsBusy用来初始化和扩容数组表使用,这里没有必要用阻塞锁,当一次线程发现当前下标的元素获取锁失败后,会尝试获取其他下表的元素的锁。更详细的说明敬请期待 Java并发编程基础之并发包源码剖析 一书的出版

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • HttpClient的异步调用,你造?

    HttpClient提供了两种I/O模型:经典的java阻塞I/O模型和基于Java NIO的异步非阻塞事件驱动I/O模型。

    加多
  • 什么是重排序与中断

    Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序可以保证最终执行的结果是与程序顺序执行的结果一致,并且只会对不存在数据依赖性的指令进行重排序,...

    加多
  • ThreadLocal原理探究

    多线程访问同一个共享变量特别容易出现并发问题,特别是多个线程需要对一个共享变量进行写入时候,为了保证线程安全,一般需要使用者在访问共享变量的时候进行适当的同步,...

    加多
  • 一些小知识点

    全局作用域下,let和const声明变量,变量并不会挂载到window上。存在暂时性死区。

    用户3258338
  • 如何在 Spring 异步调用中传递上下文

    异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。异步调用...

    猿天地
  • 2019-2-24-元组投影初始值设定项

    使用过命名元组的同学都知道,命名元组可以使用“有意义的字段名”来代替Item,用于表示元组的成员。在C#7.1中引入了“元组投影初始值设定项”(tuple pr...

    黄腾霄
  • 如何在 Spring 异步调用中传递上下文什么是异步调用?

    异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。异步调用...

    aoho求索
  • 资源 | Hinton、LeCun、吴恩达......不容错过的15大机器学习课程都在这儿了

    翻译 | AI科技大本营 参与 | 刘畅 编辑 | Donna 之前,我们推送了由sky2learn整理的15大深度学习课程。这次,我们整理了15个必看的机器学...

    AI科技大本营
  • iOS——GCD的死锁案例

    在项目中,用GCD的时候非常多,但是我最近脑子里一直在问自己一个问题,死锁是什么。惭愧的是这个当初清晰的概念现在愈加模糊,考虑到自己并没有专门整理过死锁的文章,...

    Originalee
  • 巧用MOOC组合掌握机器学习

    咱们不提CES 2017上激动人心的自动驾驶产品(估计七八年之后你的驾驶证就可以扔掉了),也不细讲《最强大脑》节目里人类精英在图像识别环节被碾压(这曾经是人类可...

    王树义

扫码关注云+社区

领取腾讯云代金券