CAS的原理

CAS(Compare And Swap)比较与替换,是一种无锁算法。在不使用锁(没有线程被阻塞)的情况下实现多线程之间的变量同步。(Java.util.concurrent包中的原子类就是通过CAS来实现了乐观锁。)

CAS算法涉及到三个操作数:

  • 需要读写的内存值 V

  • 进行比较的值/期望值 A

  • 要写入的新值B

当且仅当内存值V等于期望值A时,CAS通过原子方式用新值B来更新内存V的值,比较和更新是一个原子操作,不等于时,不会进行更新,更新是一个不断循环重试的操作。

比如有t1和t2两个线程都同时去访问同一变量 56,并更新,他们会把主内存的值完全拷贝一份 到自己的工作内存空间,所以t1和t2线程的预期值都是56。

假设t1在与t2线程竞争中,线程t1能去更新变量的值,而其它线程都失败。(失败的线程并不会 被挂起,而是被告知这次竞争中失败,并可以再次发起 尝试)。t1线程去更新变量值改为57,然后写道内存中。此时对于t2来说,内存值变为57,与预期值56不一致,就操作失败了(想改的值不再是原来的值)。

(通俗解释是:CPU去更新一个值,但如果想改的值不再是原来的值,操作就失败,因为很明显,有其他操作先改变了这个值)

就是指当两者进行比较时,如果相等,则证明共享数据没有被修改,替换成新值,然后继续往下运行;如果不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作。容易看出 CAS 操作是基于共享数据不会被修改的假设,采用了类似于数据库的commit-retry 的模式。当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

链接:https://www.jianshu.com/p/ab2c8fce878b

CAS带来的问题:

1 CAS怎么处理一个线程拿到值后,另一个线程将值修改回期望值?ABA问题

在变量前面加上版本号,每次变量更新的时候变量的版本号都+1,即A->B->A就变成了1A->2B->3A。

Java.util.concurrent包中的原子类通过加时间戳解决ABA问题

2 循环时间长开销大。CAS操作如果长时间不成功,会导致其一直自旋,给CPU带来非常大的开销。

3 只能保证一个共享变量的原子操作。对一个共享变量执行操作时,CAS能够保证原子操作,但是对多个共享变量操作时,CAS是无法保证操作的原子性的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值