java 中的LongAdder
问题
(1)java8中为什么要新增LongAdder?
(2)LongAdder的实现方式?
(3)LongAdder与AtomicLong的对比?
简介
LongAdder是java8中新增的原子类,在多线程环境中,它比AtomicLong性能要高出不少,特别是写多的场景。
原理
LongAdder的原理是,在最初无竞争时,只更新base的值,当有多线程竞争时通过分段的思想,让不同的线程更新不同的段,最后把这些段相加就得到了完整的LongAdder存储的值。
源码分析
LongAdder继承自Striped64抽象类,Striped64中定义了Cell内部类和各重要属性。
主要内部类
// Striped64中的内部类,使用@sun.misc.Contended注解,说明里面的值消除伪共享
@sun.misc.Contended static final class Cell {// 存储元素的值,使用volatile修饰保证可见性volatile long value;Cell(long x) { value = x; }// CAS更新value的值final boolean cas(long cmp, long val) {return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);}// Unsafe实例private static final sun.misc.Unsafe UNSAFE;// value字段的偏移量private static final long valueOffset;static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class<?> ak = Cell.class;valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value"));} catch (Exception e) {throw new Error(e);}}
}
Cell类使用@sun.misc.Contended注解,说明是要避免伪共享的。
使用Unsafe的CAS更新value的值,其中value的值使用volatile修饰,保证可见性。
主要属性
// 这三个属性都在Striped64中
// cells数组,存储各个段的值
transient volatile Cell[] cells;
// 最初无竞争时使用的,也算一个特殊的段
transient volatile long base;
// 标记当前是否有线程在创建或扩容cells,或者在创建Cell
// 通过CAS更新该值,相当于是一个锁
transient volatile int cellsBusy;
LongAdder VS AtomicLong 性能对比
public class LongAdderVSAtomicLongTest {public static void main(String[] args){testAtomicLongVSLongAdder(1, 10000000);testAtomicLongVSLongAdder(10, 10000000);testAtomicLongVSLongAdder(20, 10000000);testAtomicLongVSLongAdder(40, 10000000);testAtomicLongVSLongAdder(80, 10000000);}static void testAtomicLongVSLongAdder(final int threadCount, final int times){try {System.out.println("threadCount:" + threadCount + ", times:" + times);long start = System.currentTimeMillis();testLongAdder(threadCount, times);System.out.println("LongAdder elapse:" + (System.currentTimeMillis() - start) + "ms");long start2 = System.currentTimeMillis();testAtomicLong(threadCount, times);System.out.println("AtomicLong elapse:" + (System.currentTimeMillis() - start2) + "ms");} catch (InterruptedException e) {e.printStackTrace();}}static void testAtomicLong(final int threadCount, final int times) throws InterruptedException {AtomicLong atomicLong = new AtomicLong();List<Thread> list = new ArrayList<>();for (int i=0;i<threadCount;i++){list.add(new Thread(() -> {for (int j = 0; j<times; j++){atomicLong.incrementAndGet();}}));}for (Thread thread : list){thread.start();}for (Thread thread : list){thread.join();}}static void testLongAdder(final int threadCount, final int times) throws InterruptedException {LongAdder longAdder = new LongAdder();List<Thread> list = new ArrayList<>();for (int i=0;i<threadCount;i++){list.add(new Thread(() -> {for (int j = 0; j<times; j++){longAdder.add(1);}}));}for (Thread thread : list){thread.start();}for (Thread thread : list){thread.join();}}
}
可以看到当只有一个线程的时候,AtomicLong反而性能更高,随着线程越来越多,AtomicLong的性能急剧下降,而LongAdder的性能影响很小。
总结
(1)LongAdder通过base和cells数组来存储值;
(2)不同的线程会hash到不同的cell上去更新,减少了竞争;
(3)LongAdder的性能非常高,最终会达到一种无竞争的状态;
java 中的LongAdder相关推荐
- Java中的LongAdder和AtomicLong有什么区别?
● Java中的LongAdder和AtomicLong有什么区别? 考点:JDK 参考回答: JDK1.8引入了LongAdder类.CAS机制就是,在一个死循环内,不断尝试修改目标值,直到修改成功 ...
- java中decrement,Java LongAdder decrement()用法及代码示例
Java中的LongAdder类创建一个初始和为零的新加法器. Java.LongAdder.decrement()是Java中的内置方法,可将值减少1. 用法: public void decrem ...
- java中decrement,Java LongAdder decrement()用法及代碼示例
Java中的LongAdder類創建一個初始和為零的新加法器. Java.LongAdder.decrement()是Java中的內置方法,可將值減少1. 用法: public void decrem ...
- Java 中 10 大坑爹功能!
今天我们就来聊一下 Java 中的 10 大坑爹功能,它们分别是: 1.switch必须加上break才结束 2.逻辑运算符的"短路"现象 3.数组下标从零开始 4.ArrayLi ...
- Java中的一些坑,汇总篇(2万字)
Photo @ Drew Farwell 文 | 常意 1.前言 查看全文 http://www.taodudu.cc/news/show-1122809.html 相关文章: 高并发系统 3 大 ...
- java synchronized atomic_atomic 包、synchronized | Java 中线程安全
相关阅读 之前已经说过了,我们在保证线程安全的时候主要就是保证线程安全的 3 大特性,原子性.可见性.有序性.而在 JMM 的层面也已经做了相关的操作,比方说 JMM 定义的 8 种原子操作以及相关的 ...
- Java中常用的原子类
文章目录 一.什么是原子类 二.原子类的底层实现 三.常用的原子类 3.1.AtomicInteger与AtomicLong 3.2.LongAdder 四.原子类的性能测试 4.1.测试程序 4.2 ...
- 【236期】ElasticSearch 进阶:一文全览各种 ES 查询在 Java 中的实现
点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方有惊喜,留言必回,有问必答! 每天 08:15 更新文章,每天进步一点点... ...
- JAVA中J.U.C 包下并发类的应用
文章目录 JUC包中的锁应用 Lock接口及ReentrantLock对象分析及应用? Condition接口对象分析与应用? ReadWriteLock接口及实现类分析与应用? StampedLoc ...
最新文章
- gdb coredump
- python | ^ ~
- 从0开始学springboot之启蒙篇
- 计算机科学是对描述和变换,对计算机科学发展的思考
- iis windows phpstudy安装redis扩展
- Java常用接口与类——main方法/Object类/Scanner类
- leetcode力扣49. 字母异位词分组
- 超定方程组的经典Gram-Schmidt正交化解法
- DPDK初始化分析(一)
- android 改机型玩王者,全机型60帧一键修改
- 获取微信jssdk权限影响ajax,微信jssdk中请求得到access_token遇到跨域问题,改写为jsonp,报错...
- 从微信跳转到appstore下载App
- The PyTorch-Kaldi Speech Recognition Toolkit
- 一篇文章轻松搞定SpringSecurity权限框架!
- vue 父传子props
- resizeEvent , paintEvent事件触发原因
- 路由器、交换机、服务器等网络设备常见故障及解决方法
- Linux 终端文件管理器 —— ranger
- 网站用户行为数据收集和分析方法
- 1分钟链圈 | EOS区块生产者达成一项新协议,降低新账户创建成本并给予新账号免费RAM...
热门文章
- 海龟绘图两小时上手C语言 - 4 任意螺旋线
- dnf显示与服务器数据异常怎么办啊,DNF:你这该死的数据异常网络中断连接,让我心在痛泪在流...
- 柯洁:我受够了AI围棋;联发科校园招聘,应届生年薪约45万元;Chrome 100发布 | 极客头条...
- 苹果市值突破2万亿美元;华为推出PC版HMS“擎云生态”;Android11将强制应用使用内置相机| 极客头条...
- 阿里 AI 研究成果入选国际顶会 ICML 2020,AI 推理速度提升 3 倍
- 知识图谱够火,但底层技术环节还差点火候 | AI 技术生态论
- 阿里回应“拼多多员工淘宝账号被封”;微信脸书合办新冠病毒黑客马拉松;Kubernetes 1.18发布 | 极客头条...
- 腾讯 QQ 产品已经实现全量上云;中科院计算所发明新编程语言“木兰”;Electron 7.1.9 发布 | 极客头条...
- 开源技术、开放使用、业务导向的大数据平台,助力银行数字化转型
- 收购一家毁一家,雅虎到底杀死了多少好产品?