问题

(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相关推荐

  1. Java中的LongAdder和AtomicLong有什么区别?

    ● Java中的LongAdder和AtomicLong有什么区别? 考点:JDK 参考回答: JDK1.8引入了LongAdder类.CAS机制就是,在一个死循环内,不断尝试修改目标值,直到修改成功 ...

  2. java中decrement,Java LongAdder decrement()用法及代码示例

    Java中的LongAdder类创建一个初始和为零的新加法器. Java.LongAdder.decrement()是Java中的内置方法,可将值减少1. 用法: public void decrem ...

  3. java中decrement,Java LongAdder decrement()用法及代碼示例

    Java中的LongAdder類創建一個初始和為零的新加法器. Java.LongAdder.decrement()是Java中的內置方法,可將值減少1. 用法: public void decrem ...

  4. Java 中 10 大坑爹功能!

    今天我们就来聊一下 Java 中的 10 大坑爹功能,它们分别是: 1.switch必须加上break才结束 2.逻辑运算符的"短路"现象 3.数组下标从零开始 4.ArrayLi ...

  5. Java中的一些坑,汇总篇(2万字)

    Photo @ Drew Farwell 文  |  常意 1.前言 查看全文 http://www.taodudu.cc/news/show-1122809.html 相关文章: 高并发系统 3 大 ...

  6. java synchronized atomic_atomic 包、synchronized | Java 中线程安全

    相关阅读 之前已经说过了,我们在保证线程安全的时候主要就是保证线程安全的 3 大特性,原子性.可见性.有序性.而在 JMM 的层面也已经做了相关的操作,比方说 JMM 定义的 8 种原子操作以及相关的 ...

  7. Java中常用的原子类

    文章目录 一.什么是原子类 二.原子类的底层实现 三.常用的原子类 3.1.AtomicInteger与AtomicLong 3.2.LongAdder 四.原子类的性能测试 4.1.测试程序 4.2 ...

  8. 【236期】ElasticSearch 进阶:一文全览各种 ES 查询在 Java 中的实现

    点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方有惊喜,留言必回,有问必答! 每天 08:15 更新文章,每天进步一点点... ...

  9. JAVA中J.U.C 包下并发类的应用

    文章目录 JUC包中的锁应用 Lock接口及ReentrantLock对象分析及应用? Condition接口对象分析与应用? ReadWriteLock接口及实现类分析与应用? StampedLoc ...

最新文章

  1. gdb coredump
  2. python | ^ ~
  3. 从0开始学springboot之启蒙篇
  4. 计算机科学是对描述和变换,对计算机科学发展的思考
  5. iis windows phpstudy安装redis扩展
  6. Java常用接口与类——main方法/Object类/Scanner类
  7. leetcode力扣49. 字母异位词分组
  8. 超定方程组的经典Gram-Schmidt正交化解法
  9. DPDK初始化分析(一)
  10. android 改机型玩王者,全机型60帧一键修改
  11. 获取微信jssdk权限影响ajax,微信jssdk中请求得到access_token遇到跨域问题,改写为jsonp,报错...
  12. 从微信跳转到appstore下载App
  13. The PyTorch-Kaldi Speech Recognition Toolkit
  14. 一篇文章轻松搞定SpringSecurity权限框架!
  15. vue 父传子props
  16. resizeEvent , paintEvent事件触发原因
  17. 路由器、交换机、服务器等网络设备常见故障及解决方法
  18. Linux 终端文件管理器 —— ranger
  19. 网站用户行为数据收集和分析方法
  20. 1分钟链圈 | EOS区块生产者达成一项新协议,降低新账户创建成本并给予新账号免费RAM...

热门文章

  1. 海龟绘图两小时上手C语言 - 4 任意螺旋线
  2. dnf显示与服务器数据异常怎么办啊,DNF:你这该死的数据异常网络中断连接,让我心在痛泪在流...
  3. 柯洁:我受够了AI围棋;联发科校园招聘,应届生年薪约45万元;Chrome 100发布 | 极客头条...
  4. 苹果市值突破2万亿美元;华为推出PC版HMS“擎云生态”;Android11将强制应用使用内置相机| 极客头条...
  5. 阿里 AI 研究成果入选国际顶会 ICML 2020,AI 推理速度提升 3 倍
  6. 知识图谱够火,但底层技术环节还差点火候 | AI 技术生态论
  7. 阿里回应“拼多多员工淘宝账号被封”;微信脸书合办新冠病毒黑客马拉松;Kubernetes 1.18发布 | 极客头条...
  8. 腾讯 QQ 产品已经实现全量上云;中科院计算所发明新编程语言“木兰”;Electron 7.1.9 发布 | 极客头条...
  9. 开源技术、开放使用、业务导向的大数据平台,助力银行数字化转型
  10. 收购一家毁一家,雅虎到底杀死了多少好产品?