AtomicXXX 用的好好的,阿里为什么推荐使用 LongAdder?面试必问!
点击关注公众号,Java干货及时送达
面试连环炮先来一连炮简单的面试,看你能顶住几轮?
栈长:
1、多线程情况下,进行数字累加(count++)要注意什么?
张三:
要注意给累加方法加同步锁,不然会出现变量可见性问题,变量值被其他线程覆盖出现不一致的情况
栈长:
2、保证变量可见性,用 volatile 修饰不就行了吗?
张三:
volatile 是可以保证可见性,但不能保证原子性和线程安全
栈长:
3、除了加同步锁这种方案,还有别的方法吗?
张三:
还可以用 JDK 中的原子类,比如:AtomicInteger、AtomicLong,它们是通过 CAS 算法实现的一种乐观锁
栈长:
4、不错,还知道别的么?
张三:
呃……
认真的,你能顶住几轮?
这些问题是 Java 程序员面试过程中必问的,出场率贼高,Java 程序员必懂,这些题在Java面试库小程序中也都有详细答案,这里就不展开了。
你还知道别的么?最后一轮的答案就是今天的主题!
更好的选择:LongAdder你还在用 AtomicInteger、AtomicLong 原子类进行并发累加操作吗?那你就 OUT 了!
除了 AtomicInteger、AtomicLong,其实在 JDK 8 中更建议使用 LongAdder 进行原子性操作,性能更好,如果你使用的还是 JDK 7-,那当我没说,即使如此,也不能找借口不知道,毕竟 JDK 8 是现在的主流应用版本了。
阿里巴巴最新的 Java开发手册 是这么定义的:
这份阿里巴巴完整的 Java 开发手册,可以关注公众号:Java核心技术,回复:手册,即可下载高清完整版。
如果你还没有用过 LongAdder,不妨看看本文,刷新你的认知,栈长带你涨知识!
为什么搞出了 LongAdder?我们都知道在 JDK 5 中搞出了 AtomicInteger、AtomicLong 等原子类,这也是在 JDK 8 之前普遍用的原子性操作类,来看下 AtomicLong 的累加源码:
大家都知道这些原子类都是通过 CAS 算法实现的乐观锁,通过旧值和现有的值不断循环比对,直到比对成功才修改成功结束循环。
这样就会有一个问题,如果并发数很高的话,就会造成过多的没有必要的 "循环",这势必会影响 CPU 的性能。
所以,JDK 8 又搞出来了一个 LongAdder,也在 atomic 包下:
大家可以看到,在同级包中还有一个 LongAccumulator 类,这个这篇不展开,栈长下次再另开一篇具体分析,关注公众号:Java技术栈,写完我会第一时间进行推送。
LongAdder 为什么性能更好?来分析下 LongAdder 类的源码:
在 LongAdder 中维护了一个 Cell 数组,当 Cell 它不为空时,size 是 2 的次幂大小,每个 Cell 数组里面都有一个初始值为 0 的 long 变量,用来存储每个 Cell 的值:
然后其中的 sum 方法用来对 Cell 数组进行求和再加上 base 基础值进行返回:
关于 base 基础值:
LongAdder 并不会一开始就创建 Cell 数组,其本身也会维护一个 base 基础值,当 CAS 更新失败时才进行创建或者扩容。
来看下 AtomicXXX 和 LongAdder 更新对比图:
Cell 数组相当于一个分段的概念,把 AtomicXXX 中的一个值分成了多个值进行管理,当 CAS 更新失败时不再当前循环重试,而是尝试获取其他的资源锁,这样就降低了对于 AtomicXXX 中的单个资源的竞争,所以 LongAdder 的性能更高。
虽然 LongAdder 性能更好,那有没有缺点呢?
LongAdder 带来了良好的性能,代价肯定也是有的,既然维护了 Cell 数组,也就意味着要占用更多的内存空间,以空间换时间,也是值得的。
实战测试既然官方都说在高并发的情况下性能更好,事实是否如此呢?
栈长必须实战测试一翻,打消大家的疑虑!
AtomicLong 测试代码:
/***@author:栈长*@from:公众号Java技术栈*/privatestaticvoidatomicLongTest()throwsInterruptedException{longstart=System.currentTimeMillis();ExecutorServicees=Executors.newFixedThreadPool(MAX_POOL_SIZE);for(inti=0;i{for(intj=0;j LongAdder 测试代码:
/***@author:栈长*@from:公众号Java技术栈*/privatestaticvoidlongAdderTest()throwsInterruptedException{longstart=System.currentTimeMillis();ExecutorServicees=Executors.newFixedThreadPool(MAX_POOL_SIZE);for(inti=0;i{for(intj=0;j 这里只贴核心测试代码了,完整代码已上传到了 Github:
https://github.com/javastacks/javastack
测试结果:
这里测试的只有是 1 个线程,每个线程循环累加 1 次,这个没有锁竞争、没有高并发操作的场景就能看出性能上的差异了。。
栈长再不断提升 线程数、循环累加次数 ,得到了以下测试结果:
线程数 * 循环次数 AtomicLong LongAdder 1 * 1 45ms 1ms 10 * 10 55ms 2ms 10 * 100 56ms 2ms 100 * 10 58ms 10ms 100 * 100 74ms 10ms 1000 * 10 190ms 71ms 1000 * 100 217ms 73ms 1000 * 1000 194ms 81ms 1000 * 10000 301ms 114ms 1000 * 100000 1813ms 277ms 1000 * 1000000 17596ms 1629ms 图表对比:
从测试结果可以看出,LongAdder 的性能都是碾压 AtomicLong 的,最高可达 28 多倍的差距(56/2),可以说在高性能要求的高并发场景,肯定是有必要用 LongAdder 的,这也是阿里巴巴为什么建议使用 LongAdder 的原因。
当然,这只是我个人的测试,这个也和硬件配置有关系的,但毋庸置疑是,AtomicLong 的性能是更好的。另外,栈长写的 Java 多线程系列教程全部整理好了,微信搜索Java技术栈,在后台发送:Java,可以在线阅读。
总结本文以一场面试连环炮揭开了 LongAdder 的面纱,怎么解决 count++ 的线程安全性问题?
栈长再总结下:
累加方法加 synchronized/ Lock 同步锁;使用 AtomicInteger/ AtomicLong 原子类;使用 LongAdder 原子类(推荐使用);LongAdder 这个东西是 Java 8 搞出来的,用来代替 AtomicXXX,不管是否高并发场景,都完胜 AtomicXXX,它不仅可以改善性能,现在面试也问的越来越多了,大家还是有必要掌握。
虽然 LongAdder 性能更好,但也是以更多的内存空间消耗为代价的,当然,现代计算机,内存早已不是瓶颈,所以这点消耗是可以忽略不计的,性能还是最重要的,但是大家也要知道这个点。
本文实战源代码完整版已经上传:
https://github.com/javastacks/javastack
欢迎 Star 学习,公众号所有 Java 实战示例都会在这上面提供!
好了,今天的分享就到这里了,后面栈长会分享更多好玩的 Java 技术和最新的技术资讯,关注公众号Java技术栈第一时间推送,我也将主流 Java 面试题和参考答案都整理好了,在公众号后台回复关键字 "面试" 进行刷题。
最后,觉得我的文章对你用收获的话,动动小手,给个在看、转发,原创不易,栈长需要你的鼓励。
Spring Cloud 爆高危漏洞,赶紧修复!2021 年发生的 10 件技术大事!!23 种设计模式实战(很全)换掉 Log4j2!tinylog 横空出世再见单身狗!Java 创建对象的 6 种方式劲爆!Java 协程要来了!重磅官宣:Redis 对象映射框架来了!!别再写爆爆爆炸类了,试试装饰器模式!程序员精通各种技术体系,45岁求职难!Spring Boot 3.0 M1 发布,正式弃用 Java 8Spring Boot 学习笔记,这个太全了!版权声明: 本文系公众号 "Java技术栈" 原创,转载、引用本文内容请注明出处,抄袭、洗稿一律投诉侵权,后果自负,并保留追究其法律责任的权利。
关注Java技术栈看更多干货
获取 Spring Boot 实战笔记!
相关阅读
-
世界热推荐:今晚7:00直播丨下一个突破...
今晚19:00,Cocos视频号直播马上点击【预约】啦↓↓↓在运营了三年... -
NFT周刊|Magic Eden宣布支持Polygon网...
Block-986在NFT这样的市场,每周都会有相当多项目起起伏伏。在过去... -
环球今亮点!头条观察 | DeFi的兴衰与...
在比特币得到机构关注之后,许多财务专家预测世界将因为加密货币的... -
重新审视合作,体育Crypto的可靠关系才能双赢
Block-987即使在体育Crypto领域,人们的目光仍然集中在FTX上。随着... -
简讯:前端单元测试,更进一步
前端测试@2022如果从2014年Jest的第一个版本发布开始计算,前端开发... -
焦点热讯:刘强东这波操作秀
近日,刘强东发布京东全员信,信中提到:自2023年1月1日起,逐步为...