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

多线程带来的风险以及导致风险的原因 文章目录什么是线程不安全1、原子性2、可见性3、指令重排(编译器优化)4、cup的抢占式执行(万恶之源)5、多个线程同时操作了一个变量 什么是线程不安全 线程不安全就是线程执行的结果与我们预期的结果不一致。比如一个计算方法,正确的答案是+XXX,而最终的执行结果却是-XXX,这样就是线程不安全的。 造成线程不安全的主要有以下五个原因: 1、原子性 比如的 n++,其实是由三步操作组成的: 1. 从内存把数据读到 CPU 2. 进行数据更新 3. 把数据写回到 CPU 如果一个线程正在对一个变量操作,中途 阅读详情

一、前言

这篇文章给大家聊一下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分段数值加起来返回给你。

六、总结 & 思考

不知道大家有没有发现这种高并发访问下的分段处理机制,在很多地方都有类似的思想体现!因为高并发中的分段处理机制实际上是一个很常见和常用的并发优化手段。

在我们之前的一篇讲分布式锁的文章:(每秒上千订单场景下的分布式锁高并发优化实践!),也是用到了分段加锁以及自动分段迁移/合并加锁的一套机制,来大幅度几十倍的提升分布式锁的并发性能。

所以其实很多技术,思想都是有异曲同工之妙的。

攻防世界:Crypto习题之easy_RSA 在非对称加密算法中,单向函数被广泛应用,用于确保从公钥加密后的密文无法轻易推导出私钥,从而保证数据的安全性。而其中最著名的算法便是 RSA 加密算法。首先设φm:=∣1≤k≤mgcdkm1∣为欧拉函数(Euler’sche Phi-function)。pqn:=pqpqφnnpqpqφnp−1q−1e∈12...φn−1gcdφne1ended≡1φn假设我们现在有明文x以及公钥en。 阅读详情

相关推荐

ubuntu20.04安装Qt5.15.2并配置环境

qt官方取消了离线安装的方式,所以推荐在线安装,当然,如果想要自己通过源码编译也可以,参考官方文档:https://wiki.qt.io/Building_Qt_5_from_Git。 在线安装: 1.到官方网站下载:wget https://download.qt.io/official_releases/online_installers/qt-unified-linux-x64-online.run 2.修改文件权限:chmod 777 qt-unified-linux-x64-online.run

f120854632的博客 8807

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

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

lxltmac的博客 832

别再死磕SPWM了!手把手教你用STM32实现SVPWM驱动PMSM电机(附代码)

本文详细介绍了如何使用STM32实现SVPWM驱动PMSM电机,对比传统SPWM方案,SVPWM在电压利用率、电流THD、转矩脉动和稳态温升等方面均有显著提升。通过克拉克变换优化、扇区快速判断和矢量作用时间补偿等核心算法,结合STM32硬件加速技巧,实现高效电机控制。附代码示例,助力开发者快速掌握SVPWM技术。

weixin_28733777的博客 274

java的cas原理(jvm底层实现的汇编语言)

文章目录简介jvm实现原理cmpxchgllock题外话 简介 CAS (Compare And Swap)比较并交换操作。 CAS 有 3 个操作数,分别是内存位置 V、旧的预期值 A 和拟修改的新值 B。当且仅当 V 符合预期值 A 时,用新值 B 更新 V 的值,否则什么都不做。 jvm实现原理 以java中compareAndSwapInt方法为例子,位于unsafe.cpp:openjdk/hotspot/src/share/vm/prims/unsafe.cpp。 UNSAFE_ENTRY(jb

【Mr-Coolerwu】 1129

VLA、世界模型与端到端在智驾中的本质关系与工程落地

世界模型并非3D重建,而是对环境状态转移函数的可微分建模;VLA不是视觉+语言+动作的简单拼接,核心在于跨模态语义对齐。二者共同支撑具身智能系统实现从感知到行动的闭环推演,其技术价值体现在长尾场景泛化能力提升与决策延迟降低。在自动驾驶领域,真实量产方案均采用VLA架构作为多模态感知基础,嵌入轻量级世界模型以支持反事实轨迹推演,并通过WA硬件封装保障实时性,最终由端到端控制层完成像素到扭矩的语义贯通。这种混合架构已成L2+/L3智驾系统的工程共识。

weixin_34163553的博客 366

5分钟搞定Unity+Visual Studio开发环境配置(含C#游戏开发工作负载)

本文提供了一份详细的Unity与Visual Studio开发环境配置指南,帮助开发者在5分钟内完成C#游戏开发工作负载的设置。从Unity Hub安装到Visual Studio关键组件选择,再到常见问题排查,全面覆盖环境搭建的各个环节,显著提升游戏开发效率。

weixin_29014237的博客 249

CAS原子操作实现无锁及性能分析

最近在研究nginx的自旋锁的时候,又见到了GCC CAS原子操作,于是决定动手分析下CAS实现的无锁到底性能如何,网上关于CAS实现无锁的文章很多,但少有研究这种无锁的性能提升的文章,这里就以实验结果和我自己的理解逐步展开。

@Echo· 个人技术笔记 4万+

基于Simulink的风电系统背靠背变流器解耦控制仿真

本文完成了基于 Simulink 的风电背靠背变流器解耦控制仿真,实现了:✅掌握 dq 解耦控制的数学本质✅构建 MSC + GSC 完整控制链✅验证其在动态、扰动下的卓越性能✅达成高解耦度、低 THD、稳母线三大目标。

xiaoheshang_123的博客 79

java cas 性能_java使用synchronized和cas性能对比

今天使用synchronized和java unsafe cas接口对比了下同一个操作下的的相关性能,为后面多线程情况下使用synchronized同步阻塞方式或者是unsafe cas非阻塞做了一个参考。测试用例:启用多个线程进行计数相加到一亿,首先是synchronized方式;计算类如下:packagecom.wc.thread;public class SyncCounter implem...

weixin_29973493的博客 589

Node-RED教程(一):Node-RED的介绍与安装

最新最全的Node-RED,node-red教程都在这里。 本篇介绍node-red的安装。使用docker 安装node-red

知无涯 3万+

FPGA经验谈系列文章——3、逻辑级数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Xilinx FPGA开发tips系列——前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的

gzy0506的博客 1万+

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

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

weixin_33899835的博客 198

Open3D 点云变换【2025最新版】

点云平移、旋转、缩放、欧式变换的python代码实现。博客长期更新,本文最近更新时间为:2025年1月16日。

点云侠的博客 37万+

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

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

weixin_35764712的博客 246

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

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

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

weixin_39622905的博客 200

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

并发系列2-大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?【石杉的架构笔记】...

转载于:https://www.cnblogs.com/daiwei1981/p/10259147.html

weixin_33877092的博客 120

VB摄像头监控

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

大白话系列之java_并发系列2-大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?【石杉的架构笔记】...

Lua-面向对象中函数使用时冒号(:)和点(.)的区别先来看一段简单的代码: local Animal = {} function Animal:Eat( food ) print("Animal:Eat", self, food) ...61.Android适...

weixin_29196891的博客 112

【大白话说Java面试题 第110题】【并发篇】第10题:CAS 存在哪些问题?

本文深入探讨了CAS(Compare-And-Swap)在并发编程中的关键问题与解决方案。主要内容包括: 自旋开销问题:分析CAS自旋导致的CPU空转现象,量化计算其性能损耗,并提出自适应自旋、指数退避等优化方案。 单变量限制问题:指出CAS只能操作单个变量的局限性,针对多变量原子性需求,给出对象封装和锁机制等解决方法。 ABA问题:揭示值被修改又还原导致的隐患,特别在链表等数据结构中的危害,推荐使用AtomicStampedReference等版本控制方案。 文章通过对比表格和代码示例,展示了不同场景下的

Java后端 | AI智能体应用实战派 | 电脑技能行家 505

【2024Java面试突击】并发编程、线程池面试实战

最近在更新面试突击专栏,我把每一篇将字数都尽量控制在 2000 字以内,可能在文章里边写的没有那么细致,主要是提供一些 问题 以及 回答的思路 ,以及 面试中可能忽略的漏洞 ,所以在看完文章之后,如果自己简历中有这方面的内容的话,一定要认真去整理一份自己的回答,并且多查阅相关资料,如果看的文章少,就会导致学习到的内容太片面。

sinat_53467514的博客 1225

大白话聊聊Java并发面试问题之谈谈你对AQS的理解?

要点: 1,并发框架,实现加锁 2,status(CAS实现);当前线程;等待队列 一、写在前面 上一篇文章聊了一下java并发中常用的原子类的原理和Java 8的优化,具体请参见文章:大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?。 这篇文章,我们来聊聊面试的时候比较有杀伤力的一个问题:聊聊你对AQS的理解? 之前有同学反馈,去互联网公司面试,面试官聊到并发时就问...

C18298182575的博客 326

【面试突击】并发编程、线程池面试实战

欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理解 Redis 系列文章结合电商场景讲解 Redis 使用场景、中间件系列笔记和编程高频电子书! 文章导读地址:点击查看文章导读! 感谢你的关注!

qq_45260619的博客 1338

【面试专栏|Java并发编程】Java 原子类全解:AtomicInteger、LongAdder 原理与适用场景

Java原子类AtomicInteger和LongAdder是并发编程中的核心工具类。AtomicInteger基于CAS机制实现无锁原子操作,适用于低并发场景;而LongAdder采用分段累加策略,在高并发环境下性能更优。本文从底层原理、实战用法到适用场景进行对比分析,帮助开发者根据业务需求选择合适方案,并深入理解两者的实现机制与性能差异。通过代码示例和流程图直观展示使用方式,为Java并发面试提供全面解答。

m0_58782205的博客 453

【大白话说Java面试题 第129题】【并发篇】第29题:谈谈你对 ConcurrentLinkedQueue 的理解

摘要: ConcurrentLinkedQueue是Java并发包中的高性能无锁队列,基于Michael-Scott算法实现,通过CAS原子操作避免锁竞争,适用于高并发场景。其核心设计包括: 延迟更新策略(HOPS):head和tail指针并非每次操作都更新,而是间隔节点更新,减少CAS竞争。 弱一致性:size()方法需遍历链表,时间复杂度为O(n),且结果可能不精确。 与LinkedBlockingQueue对比:无锁队列吞吐量更高,但内存无界;阻塞队列支持有界和阻塞操作。 ABA问题规避:Java的垃

Java后端 | AI智能体应用实战派 | 电脑技能行家 500

大白话聊聊Java并发面试问题之谈谈你对AQS的理解?【石杉的架构笔记】

一、写在前面 上一篇文章聊了一下java并发中常用的原子类的原理和Java 8的优化,具体请参见文章:《大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?》。 这篇文章,我们来聊聊面试的时候比较有杀伤力的一个问题:聊聊你对AQS的理解? 之前有同学反馈,去互联网公司面试,面试官聊到并发时就问到了这个问题。当时那位同学内心估计受到了一万点伤害。。。 因为首先,很多人还真的连AQS是什么都不知道,可能听都没听说过。或者有的人听说过AQS这个名词,但是可能连具体全称怎...

从2026-09-21开始专注于AI,以前是后端研发、大数据研发等 404

AtomicLong 与 LongAdder(CAS机制的优化)

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

eluanshi12的博客 1523
上一篇: 为什么要前后端分离?有什么优缺点?
下一篇: 双亲委派模型:大厂高频面试题,轻松应对
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值