Java8中的LongAdder类,提升CAS性能

Java8中的LongAdder类,大大提升CAS性能! 这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。 阅读详情

这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。

因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还是值得给大家聊一聊。

场景引入,问题凸现

好,我们正式开始!假设多个线程需要对一个变量不停的累加1,比如说下面这段代码:

实际上,上面那段代码是不ok的,因为多个线程直接这样并发的对一个data变量进行修改,是线程不安全性的行为,会导致data值的变化不遵照预期的值来改变。

举个例子,比如说20个线程分别对data执行一次data++操作,我们以为最后data的值会变成20,其实不是。

最后可能data的值是18,或者是19,都有可能,因为多线程并发操作下,就是会有这种安全问题,导致数据结果不准确。

至于为什么会不准确?那不在本文讨论的范围里,因为这个一般只要是学过java的同学,肯定都了解过多线程并发问题。

初步的解决方案:synchronized

所以,对于上面的代码,一般我们会改造一下,让他通过加锁的方式变成线程安全的:

这个时候,代码就是线程安全的了,因为我们加了synchronized,也就是让每个线程要进入increment()方法之前先得尝试加锁,同一时间只有一个线程能加锁,其他线程需要等待锁。

通过这样处理,就可以保证换个data每次都会累加1,不会出现数据错乱的问题。

老规矩!我们来看看下面的图,感受一下synchronized加锁下的效果和氛围,相当于N个线程一个一个的排队在更新那个数值。

但是,如此简单的data++操作,都要加一个重磅的synchronized锁来解决多线程并发问题,就有点杀鸡用牛刀,大材小用了。

虽然随着Java版本更新,也对synchronized做了很多优化,但是处理这种简单的累加操作,仍然显得“太重了”。人家synchronized是可以解决更加复杂的并发编程场景和问题的。

而且,在这个场景下,你要是用synchronized,不就相当于让各个线程串行化了么?一个接一个的排队,加锁,处理数据,释放锁,下一个再进来。

更高效的方案:Atomic原子类及其底层原理

对于这种简单的data++类的操作,其实我们完全可以换一种做法,java并发包下面提供了一系列的Atomic原子类,比如说AtomicInteger。

他可以保证多线程并发安全的情况下,高性能的并发更新一个数值。我们来看下面的代码:

大家看上面的代码,是不是很简单!多个线程可以并发的执行AtomicInteger的incrementAndGet()方法,意思就是给我把data的值累加1,接着返回累加后最新的值。

这个代码里,就没有看到加锁和释放锁这一说了吧!

实际上,Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性

那什么是CAS呢?他的全称是:Compare and Set,也就是先比较再设置的意思。

话不多说,先上图!

我们来看上面的图,假如说有3个线程并发的要修改一个AtomicInteger的值,他们底层的机制如下:

首先,每个线程都会先获取当前的值,接着走一个原子的CAS操作,原子的意思就是这个CAS操作一定是自己完整执行完的,不会被别人打断。

然后CAS操作里,会比较一下说,唉!大兄弟!现在你的值是不是刚才我获取到的那个值啊?

如果是的话,bingo!说明没人改过这个值,那你给我设置成累加1之后的一个值好了!

同理,如果有人在执行CAS的时候,发现自己之前获取的值跟当前的值不一样,会导致CAS失败,失败之后,进入一个无限循环,再次获取值,接着执行CAS操作!

好!现在我们对照着上面的图,来看一下这整个过程:

  • 首先第一步,我们假设线程一咔嚓一下过来了,然后对AtomicInteger执行incrementAndGet()操作,他底层就会先获取AtomicInteger当前的值,这个值就是0。
  • 此时没有别的线程跟他抢!他也不管那么多,直接执行原子的CAS操作,问问人家说:兄弟,你现在值还是0吗?
  • 如果是,说明没人修改过啊!太好了,给我累加1,设置为1。于是AtomicInteger的值变为1!
  • 接着线程2和线程3同时跑了过来,因为底层不是基于锁机制,都是无锁化的CAS机制,所以他们俩可能会并发的同时执行incrementAndGet()操作。
  • 然后俩人都获取到了当前AtomicInteger的值,就是1
  • 接着线程2抢先一步发起了原子的CAS操作!注意,CAS是原子的,此时就他一个线程在执行!
  • 然后线程2问:兄弟,你现在值还是1吗?如果是,太好了,说明没人改过,我来改成2

好了,此时AtomicInteger的值变为了2。关键点来了: 现在线程3接着发起了CAS操作,但是他手上还是拿着之前获取到的那个1啊!

线程3此时会问问说:兄弟,你现在值还是1吗?

噩耗传来!!! 这个时候的值是2啊!线程3哭泣了,他说,居然有人在这个期间改过值。算了,那我还是重新再获取一次值吧,于是获取到了最新的值,值为2。

然后再次发起CAS操作,问问,现在值是2吗?是的!太好了,没人改,我抓紧改,此时AtomicInteger值变为3!

上述整个过程,就是所谓Atomic原子类的原理,没有基于加锁机制串行化,而是基于CAS机制:先获取一个值,然后发起CAS,比较这个值被人改过没?如果没有,就更改值!这个CAS是原子的,别人不会打断你!

通过这个机制,不需要加锁这么重量级的机制,也可以用轻量级的方式实现多个线程安全的并发的修改某个数值。

Java 8对CAS机制的优化

但是这个CAS有没有问题呢?肯定是有的。比如说大量的线程同时并发修改一个AtomicInteger,可能有很多线程会不停的自旋,进入一个无限重复的循环中。

这些线程不停地获取值,然后发起CAS操作,但是发现这个值被别人改过了,于是再次进入下一个循环,获取值,发起CAS操作又失败了,再次进入下一个循环。

在大量线程高并发更新AtomicInteger的时候,这种问题可能会比较明显,导致大量线程空循环,自旋转,性能和效率都不是特别好。

于是,当当当当,Java 8推出了一个新的类,LongAdder,他就是尝试使用分段CAS以及自动分段迁移的方式来大幅度提升多线程高并发执行CAS操作的性能!

在LongAdder的底层实现中,首先有一个base值,刚开始多线程来不停的累加数值,都是对base进行累加的,比如刚开始累加成了base = 5。

接着如果发现并发更新的线程数量过多,就会开始施行分段CAS的机制,也就是内部会搞一个Cell数组,每个数组是一个数值分段。

这时,让大量的线程分别去对不同Cell内部的value值进行CAS累加操作,这样就把CAS计算压力分散到了不同的Cell分段数值中了!

这样就可以大幅度的降低多线程并发更新同一个数值时出现的无限循环的问题,大幅度提升了多线程并发更新数值的性能和效率!

而且他内部实现了自动分段迁移的机制,也就是如果某个Cell的value执行CAS失败了,那么就会自动去找另外一个Cell分段内的value值进行CAS操作。

这样也解决了线程空旋转、自旋不停等待执行CAS操作的问题,让一个线程过来执行CAS时可以尽快的完成这个操作。

最后,如果你要从LongAdder中获取当前累加的总值,就会把base值和所有Cell分段数值加起来返回给你。

从DWS到设备树:MTK平台LK阶段GPIO初始化的隐秘路径与调试实战 本文深入探讨了MTK平台LK阶段GPIO初始化的完整流程,揭示了从DWS配置到设备树生成的隐秘转换路径。通过分析MT6768等平台的启动框架,提供了针对preloader到LK阶段GPIO初始化异常的实战调试方法与最佳实践,帮助开发者有效解决硬件与软件配置不匹配的常见问题。 阅读详情

相关推荐

推荐系统公平性之流行度偏差(fairness in recommender systems -- popularity bias)

主要参考论文:《The Unfairness of Popularity Bias in Recommendation》 RMSE@RecSys 2019 流行度偏差是什么 先定义流行物品和非流行物品。下图是(Movielens 1M)数据集中物品的评分情况。 图的横坐标表示不同物品,纵坐标表示物品的评分次数。可以看出只有少部分物品得到了很多的评分,大部分曲线尾部的物品都只有少量的评分,我们也把这部分物品称为长尾物品。在本文中,我们取曲线的前20%对应的物品为流行物品,剩余的为非流行物品(长尾物品)。 然

beilizhang的博客 5309

LongAdder

文章目录LongAdderAtomicLong VS LongAdderLongAdder核心思想:将热点数据分离。 CAS 底层实现是在一个死循环中不断地尝试修改目标值,直到修改成功。如果竞争不激烈的时候,修改成功率很高,否则失败率很高。在失败的时候,这些重复的原子性操作会耗费性能。(不停的自旋,进入一个无限重复的循环中) LongAdder LongAdder,尝试使用分段CAS以及自动分段迁移的方式来大幅度提升多线程高并发执行CAS操作的性能!(JDK1.8新特性) 在LongAdder的底层实

m0_54202121的博客 390

Meta-World环境实战解析:pick-place-v2中的状态观测与动作控制

本文深入解析了Meta-World中pick-place-v2环境的强化学习实战要点。文章详细拆解了39维状态观测向量的构成与意义,包括机械臂末端、物体位置及目标坐标,并揭示了默认部分可观测设置的潜在影响。同时,阐述了4维动作空间的控制逻辑与奖励函数的分阶段设计,为训练高效稳定的抓放策略提供了核心指导与实用调优技巧。

weixin_29184371的博客 78

LongAdder 简介

LongAdder 简介

红血哥 955

移动机器人底盘-四轮差速模型(四轮独立)

对于底盘的前轮和后轮来说,其速度是同步的,那么在理想条件下,可以将底盘运动视为以ICR为圆心做圆周运动,对于四个轮子来说,圆周运动的角速度是一致的,圆周运动圆心ICR始终位于底盘几何中心COG的y轴延长线上,ICR与COG之间的距离。有关,整个底盘的速度位于速度瞬心COM处,用。四轮差速底盘设定左轮、右轮得速度分别为。圆周运动的角速度公式如式1所示。受约束,约束与圆周运动的角速度。合成,设四个轮子的速度分别为。,设左轮和右轮之间的轴距为。为圆周运动角速度,线速度为。,其均由预设目标速度。

Moresweet 猫甜 1万+

现代控制理论(4)——李雅普诺夫稳定性理论

文章目录

wang7301的博客 5万+

java并发编程——LongAdder类解析

LongAdder类解析 一、LongAdder介绍         前面讲过,AtomicLong通过CAS提供了非阻塞的原子操作,相比使用阻塞算法的同步器来说它的性能已经很好了,但是JDK开发组并不满足于此。使用AtomicLong时,在高并发行下大量线程会同时去竞争更新同一个原子变量,但是由于同时只有一个线程的CAS操作会成功,这就导致了大量线程竞争失败后,会通过无限循环不断进行自旋尝试CAS的操作,而这会白白浪费CPU资源。     &nb

weixin_42789698的博客 191

手把手教你学Simulink--基于新型通信技术集成的场景实例:无人机利用激光通信实现高速率数据传输

摘要: 本文基于Simulink搭建无人机激光通信仿真系统,解决传统射频通信带宽不足问题。系统通过五层架构(发射机、信道、PAT系统、接收机、性能分析)实现Gbps级高速传输,重点建模大气衰减(雾/雨)、光束发散、PAT精跟踪(Stateflow+PID控制)等核心模块。仿真结果显示:晴天链路可达2.5Gbps(BER 1e-8),浓雾下链路中断,验证了雾是主要性能限制因素。案例涵盖调制方式选择、动态环境仿真及3D可视化,为无人机高速数据传输提供可扩展的仿真框架,并指出混合FSO/RF、AI-PAT等优化方

MHD0815的博客 182

CAS、AtomicInteger和LongAdder原理

深入学习cas,以及juc下用cas实现的原子整数、原子小数、原子引用、自增器底层原理,unsafe类,这篇就够了!

weixin_54232666的博客 621

Open3D——点云构建Delaunay三角网【2026最新版】

点云构建Delaunay三角网

点云侠的博客 8372

Java数据可视化实战:基于JFreeChart的数学函数绘图工具开发

JFreeChart是一个开源的Java图表库,适用于Swing和JavaFX应用程序。折线图和面积图柱状图和饼图散点图和气泡图组合图表3D图表等实现自定义数学表达式解析:java复制下载throw new IllegalArgumentException("表达式不能为空");// 验证表达式try {}");throw new IllegalArgumentException("无效的数学表达式: " + e.getMessage());try {

2201_76125393的博客 367

17.高并发场景下CAS效率的优化

LongAdder的基本思路就是分散热点,将value值分散到一个数组中,不同线程会命中不同槽中的元素,每个线程只能对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多了。LongAdder的实现思路其实和CurrentHashMap中分段使用的原理非常相似,本质上都是不同的线程,在不同的单元上进行操作,减少了线程的竞争,提高了并发的效率。总的来说,LongAdder 的设计思路清晰,将累加操作分解成多个独立的单元,通过分段累加和并行计算提高了在高并发情况下的性能表现。

q1372302825的博客 1690

OCR文字识别基础

ocr文字识别

m0_47405013的博客 1755

Java8中的LongAdder类,大大提升CAS性能

如果没有,就更改值!同理,如果有人在执行CAS的时候,发现自己之前获取的值跟当前的值不一样,会导致CAS失败,失败之后,进入一个无限循环,再次获取值,接着执行CAS操作!这些线程不停地获取值,然后发起CAS操作,但是发现这个值被别人改过了,于是再次进入下一个循环,获取值,发起CAS操作又失败了,再次进入下一个循环。一个接一个的排队,加锁,处理数据,释放锁,下一个再进来。首先,每个线程都会先获取当前的值,接着走一个原子的CAS操作,原子的意思就是这个CAS操作一定是自己完整执行完的,不会被别人打断。...

CR2567001684的博客 276

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java并发面试问题之Java 8如何优化CAS性能

java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。 因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还是值得给大家聊一聊。 问题:假设多个线程需要对一个变量不停的累加1,怎么办,有什么问题? 《并发问题》 1.初步解决方案:synchronized 让他通过加锁的方式变成线程安全的: private int data = 0 ; public synchronized v

徐大叔学IT 278

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

java cas 性能_大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?

一、前情回顾这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还是值得给大家聊一聊。二、场景引入,问题凸现好,我们正式开始!假设多个线程需要对一个变量不停的累加1,比如说下面这段代码:实际上,上...

weixin_33899835的博客 198

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

大白话Java并发面试问题之Java 8如何优化CAS性能?

这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还是值得给大家聊一聊。好,我们正式开始!假设多个线程需要对一个变量不停的累加1,比如说下面这段代码:实际上,上面那段代码是不ok的,因为多个线程直接这样并发的对一个data变量进行修改,是线程不安全性的行为,会导致data值的变化不遵照预期的值来改变。举个

JavaShark的博客 339

大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?

一、前情回顾 上篇文章给大家聊了一下volatile的原理,具体参见:大白话聊聊Java并发面试问题之volatile到底是什么?。 这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。 因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还...

C18298182575的博客 331

Java8 如何优化CAS性能

Java8 如何优化CAS性能 问题显性 假设多个线程需要对⼀个变量不停的累加 1,⽐如说下⾯这段代码: 因为多个线程直接这样并发的对⼀个 data 变量进⾏修改,是线程不安全性的⾏为,会导致 data 值的变化不遵照预期的值来改变。 ⽐如说 20 个线程分别对 data 执⾏⼀次 data++ 操作,我们以为最后 data 的值会变成 20,其实不是。最后可能 data 的值是 18,或者是 19,都有可能,因为多线程并发操作下,就是会有这种安全问题,导致数据结果不准确。 解决方案1:synchroni

songqiang880809的博客 314

AtomicXXX 用得好好的,阿里为什么推荐使用 LongAdder?面试必问

本文以一场面试连环炮揭开了LongAdder的面纱,怎么解决count++的线程安全性问题?栈长再总结下累加方法加synchronized/Lock同步锁;使用AtomicInteger/AtomicLong原子类;使用LongAdder原子类(推荐使用);LongAdder这个东西是Java8搞出来的,用来代替AtomicXXX,不管是否高并发场景,都完胜AtomicXXX,它不仅可以改善性能,现在面试也问的越来越多了,大家还是有必要掌握。https。......

Park33的博客 197

多线程如何打断点_大白话Java并发面试问题之Java 8如何优化CAS性能?

专注于Java领域优质技术,欢迎关注来自:石杉的架构笔记一、前言这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还是值得给大家聊一聊。二、场景引入,问题凸现好,我们正式开始!假设多个线程需要对...

weixin_39622905的博客 200

LongAdder类

java并发编程之美 学习笔记 AtomicLong的局限性 JUC并发包中包含有Atomic*原子操作类,他们的原理类似,下面以AtomicLong类似。 在Unsafe类对AtomicLong做了比较详细的介绍,这里不再赘述。 这里只分析下这个AtomicLong的局限性: //java.util.concurrent.atomic.AtomicLong public final lo...

dark 130

AtomicLong 与 LongAdder(CAS机制的优化)

线程安全性-原子性-CAS LongAdder是java8为我们提供的新的类,跟AtomicLong有相同的效果。是对CAS机制的优化。 AtomicLong: //变量声明 public static AtomicLong count = new AtomicLong(0); //变量操作 count.incrementAndGet(); //变量取值 count.get(); LongAdd...

eluanshi12的博客 1523

并发执行变成串行_大白话Java并发面试问题之Java 8如何优化CAS性能?

专注于Java领域优质技术,欢迎关注来自:石杉的架构笔记一、前言这篇文章给大家聊一下java并发包下的CAS相关的原子操作,以及Java 8如何改进和优化CAS操作的性能。因为Atomic系列的原子类,无论在并发编程、JDK源码、还是各种开源项目中,都经常用到。而且在Java并发面试中,这一块也属于比较高频的考点,所以还是值得给大家聊一聊。二、场景引入,问题凸现好,我们正式开始!假设多个线程需要对...

weixin_35764712的博客 246

LongAdder:连我都不了解,还天天秀 ConcurrentHashMap ?

这句话依旧是有两个含义的,第一个是进行 cas 操作,第二个是对操作的结果进行取反,取反自然没什么好说的,重点是 casBase 这个方法(看下下面的截图,casBase 调用的是本地的方法,所以不同在点进去深看了,【我们重点来看看这个方法作为判断条件的含义】)。这个是对 CAS 的最最表面的解释,所谓的期望值其实可以理解为这个对象原始的值,旧值也可以理解为当前对象的原始值,也就是说只有在该对象的值没有被改变过的情况下,才回去改变该值,不明白的朋友就不要深究了。上面的条件其实是 3 种,为何?

u011135505的博客 866

Java多线程系列(四)—CAS操作和Automic原子类

Java多线程系列(四)—CAS操作和Automic原子类 由于线程安全需要保证原子性和可见性,而volatile关键字修饰的变量仅能保证可见性不能保证原子性,因此像i++这种非原子操作就是非线程安全的;为了保证原子性,JDK引入了原子操作类,放在在java.util.concurrent.automic包下; Automic原子类底层是通过CAS实现,线程的重试会造成效率较低,

tuzhenyu的博客 2725
上一篇: 高并发系统建设经验总结
下一篇: HTTP/3正式发布,深入理解HTTP/3协议
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值