深入浅出多线程编程实战(四)CAS与ABA问题


一、CAS

CAS全称:Compare-And-Swap(比较 and 替换),它是一条CPU并发原语
在日常开发中基本不会直接使用CAS操作,因为这个操作比较复杂,我们一般通过一些JDK封装好的并发工具类,这些类在java.util.concurrent包下,这个包下的工具类很多都用到了CAS操作。
在这里插入图片描述
以上就是CAS执行流程,当该线程开始后会先读取要修改的值E的当前值,然后再去执行操作(如自增、自减等),当执行完操作后再去判断当前E值和之前读取到的预期值A是否相同,如果不相同则再次获取当前值E继续以上流程,直到当前值与预期值相同,才会对当前值E做出修改,修改成功后该线程CAS操作结束。

CAS底层:
是使用汇编语言实现的,也就是机器语言,汇编语言使用lock cmpxchg指令,对当前值加锁并修改。防止在比较的时候,值被修改,导致比较时候是没有变化,在赋值的时候被其他线程修改,防止覆盖其他线程修复后的值。
其中lock命令的作用是在当前CPU或线程在比较修改当前值的时候,其他线程不能打断。
Unsafe类:
Unsafe是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsage类存在于sun.misc包中,其内部方法操作可以像C指针一样直接操作内存
synchronized对比CAS:
synchronized是对修饰的方法,对整段代码进行了加锁,拿它对比一下CAS,sync的方式能保证数据一致性的同事并发性会下降,CAS不加锁,也能保证一致性,但其实是进行了多次比较。所以,CAS还是会有它的缺点:自旋循环的消耗性能,只能保证一个变量,还有最重要的就是会引出ABA问题。


二、ABA问题

ABA问题:如果当前的值被修改多次后又改回了之前的预期值。即原值为A,被其他线程改为B后又被改为A。此时如果继续按照当前值与预期值的比较,结果肯定是符合修改的数据的条件,会把其他线程提交上来的数据覆盖掉,这就是ABA问题。
客观的分析一下这个问题,假如我们的业务需求只需要数据的最终一致性,那么这时候的CAS算法是能够实现的,但是业务若需要按顺序或者说按照某种特定的运算规则,更或者说凡是需要追溯数据历史数据的业务,这种单纯的比较值是会造成线程安全问题的

解决方式是:给当前值E加一个版本号,每次被修改之后就版本号+1,强大的JUC并发编程包提供了一个类似于提交版本号的原子引用类AtomicStampedReference
在这里插入图片描述

评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xd聊架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值