CAS操作

一、什么是CAS?

CAS全称compare and swap,JDK提供的非阻塞原子性操作,它通过硬件保证了更新操作的原子性。它允许多线程非阻塞地对共享资源进行修改,但是同一时刻只有一个线程可以修改,其他线程并不会阻塞而是重新尝试。

二、为什么会有CAS?

一般乐观锁采取的策略。在Java中使用锁不好的地方就是当一个线程没有获得锁,就会导致线程的上下文切换,导致重新调度与开销。而volatile只能保证有序性和可见性,并不能保证原子性。CAS操作保证了原子性。

三、CAS详解

CAS,比较和交换,从语义上是两步操作,但实际上一条CPU指令就能完成。这说明,他是一个原子性操作,要么全做,要么全不做。

JDK的Unsafe类提供了compareAndSwap方法,boolean compareAndSwapLong(Object obj,Long valueOffset,long expect,long update);

参数:对象的内存地址,偏移值,期望的旧值,期望的新值

如果对象 obj中内存偏移量为 valueOffset的变量值为 expect,则使用新的值 update替换旧值 expect。这是处理器提供的一个原子性操作。

CAS经典问题:ABA问题

假如线程1使用CAS修改初始值为A的变量X(X=A),那么线程1首先会获取当前变量X的值(A),然后使用CAS操作尝试修改X的值为B,如果使用CAS修改成功了,那么程序运行一定是正常的吗?其实未必,这是因为有可能在线程1获取到变量X的值A后,在执行CAS之前,线程2使用了CAS修改了变量X值为B,然后又使用了CAS操作使得变量X值为A,虽然线程A执行了CAS操作时X=A,但是这个A已经不是线程1获取到的A了。这就是ABA问题。ABA问题的产生是因为变量的状态值产生了环形转换,就是变量值可以从A到B,也可以B到A,如果变量的值只能朝着一个方向转换,例如A到B,B到C,不构成环路,就不会存在这个问题。JDK中的AtomicStampedReference类给每个变量的状态值都配备了一个时间戳,从而避免了ABA问题。或者是使用版本号,一个数据一个版本号,版本号不同数据值相同,也不会进行修改。

ABA问题会导致什么后果?

摘录自:CAS的ABA问题,ABA问题会导致什么后

对于像库存数据的变化,通常来说,不会对结果造成影响。但是对于栈来说就会有影响。

再看一个堆栈操作的例子:

并发1(上):读取栈顶的元素为“A1”

并发2:进行了2次出栈

并发3:又进行了1次出栈

并发1(下):实施CAS乐观锁,发现栈顶还是“A1”,于是修改为A2

此时会出现系统错误,因为此“A1”非彼“A1”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值