CAS问题

CAS

compare and swap

一个特殊的 CPU 指令 完成的工作,就是 "比较和交换"

这个 cpu 指令本身就是"原子的";

所以基于 cas 指令:给编写线程安全的代码打开了新的大门;

之前线程安全都是靠 加锁 ;导致的结果就是 阻塞===> 性能降低;

使用 CAS ,不仅不涉及加锁,也不会阻塞,合理使用也能保证线程安全(无锁编程)

CAS 本身是 CPU 指令;

操作系统 对 指令 进行了 封装;

jvm 又对 操作系统提供的 api 又封装了一层;

java 中 cas 的 api 放到了 unsafe包(不安全的)里(涉及到一些底层内容,使用不当会带来风险);

java标准库,对于 CAS 又进行了进一步的封装,提供了一些工具类;最主要的一个工具类,叫做 "原子类"

上述代码就处于 "线程不安全"的情况;

解决这个问题的第一个方法就是 给 写操作 加锁;

第二个方法就是 使用原子类;

这里的内容,就没有加锁,也能保证线程安全;

之前的 count++ 是cpu的 三个指令;

多个线程的写操作是三个指令,会相互穿插执行,引起线程不安全;

此处的 getAndIncrement 对变量的修改,是一个 CAS 指令;

一个指令就是原子的;加锁就是为了将三个指令 变成 一个指令 让它成为原子的;

不使用 原子类 的 写操作;

使用了 原子类 的写操作

CAS 中的 ABA 问题

CAS 在使用的时候 关键要点是要 判定当前内存是否和寄存器中的值一样,如果一样就进行修改,不一样就什么都不做

假设有两个线程 A 和 B 同时对同一个共享变量执行 CAS 操作:

线程 A 执行 CAS 操作:

线程 A 从内存读取当前值A,并设定预期值E为A(假设A的值为 10)。

线程 A 计算出新值N(比如N = E + 1,即 11)。

线程 A 执行 CAS 操作,比较内存处的值(也就是A)是否等于预期值E。如果相等,就将内存的值修改为新值N(即把 10 改成 11),操作成功。

线程 B 执行 CAS 操作:

线程 B 同样从内存地址V读取当前值,假设线程 B 读取时,线程 A 还未完成 CAS 操作,所以线程 B 读取到的值也是 10,它也设定预期值E为 10,并计算出新值N(同样为 11)。

当线程 B 执行 CAS 操作时,如果此时线程 A 已经完成了 CAS 操作,那么内存地址V处的值已经变为 11,而线程 B 的预期值E还是 10,两者不相等,线程 B 的 CAS 操作失败,不会修改内存地址V的值。

线程 B 失败后,根据具体的业务逻辑,可以选择重试,即重新读取内存值作为预期值,重新计算新值,再次执行 CAS 操作;也可以选择放弃本次操作,执行其他逻辑。

ABA 问题

存在一种情况:内存 V 存储的数值是 0;

执行CAS 之前,另一个线程把这个值从 0 --> 10 又从 10--> 0;

在其他前程穿插的过程中,将 内存v的值 从 A 改到 B 又改回 A;

此时 CAS 并不知道 修改了值,这种情况就是 : ABA 问题

一般来说是不会出现问题

但对于 ABA 问题来说,什么时候会出现 BUG 呢?

假设,我在银行向另一个账户转账 100元 ,当我按下转账按钮时,没有反应;然后又按了一次;此时产生了两个线程,去尝试进行扣款操作(假定按照 CAS 的方式进行扣款):

线程B 先扣款成功,线程A 发现钱对不上,就不进行操作;

但如果此时在 线程B 扣款成功的同时,线程C 向 我的账户转账了 100元;此时 线程A 就不知道 账户没有转账成功 还是 转账成功,又到账了;

对于 ABA 问题的解决方案:

1)约定数据变化时单向的(只能增加或者只能减少),不能时双向的(又是双向又是单向);

2)对于本身就必须要双向变化的数据(账户转账收款),可以引入一个 版本号-->版本号这个数字就是只能增加,不能减少;(转账1-->收款2--->转账3)

CAS本质上时 JVM 帮我们封装好的;

相关推荐
AI人工智能+电脑小能手1 分钟前
【大白话说Java面试题 第190题】【08_Kafka篇】第6题:消息队列有什么作用?
java·kafka·消息队列·系统设计·分布式架构
蚰蜒螟11 分钟前
一次 Spring AOP 与定时任务引发的死锁排查实录
java·spring·firefox
TeamDev11 分钟前
JxBrowser 9.3.1 版本发布啦!
java·前端·javascript·c#·混合应用·jxbrowser·浏览器控件
程序猿乐锅1 小时前
【数据结构与算法 | 第六篇】力扣1109,1094差分数组
java·算法·leetcode
yeflx1 小时前
速腾Airy雷达使用记录
java·服务器·网络
乐之者v1 小时前
AI编程 -- Agents.md 的简单示例
java·ai编程
无风听海2 小时前
Claude Agent Skills 的四种设计模式;从渐进式披露到最小权限
java·算法·设计模式
geovindu2 小时前
java: Facade Pattern
java·开发语言·后端·外观模式·结构型模式
listening7772 小时前
HarmonyOS 6.1 元服务深度优化:从“秒开”到“常驻”的极致体验
java·开发语言·spring
AC赳赳老秦2 小时前
司法公开数据采集应用:OpenClaw 抓取裁判文书公开信息,批量整理同类参考案例
java·大数据·python·数据挖掘·数据分析·php·openclaw