cas机制学习[已迁移]

转自:https://www.jianjunwen.com/article/71

1.介绍

CAS是英文单词Compare and Swap的缩写,翻译过来就是比较并替换。

CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B

更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

当V!=A时说明有其他线程抢先修改,会放弃当前操作,之后再重新查询V,重新尝试的过程被称为自旋(Spin)。

//上述链接中有非常清晰的例子和图,有助于理解。

2.缺点

2.1 CPU开销过大

在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。(应该是自旋尝试的过程仍然占用cpu时间。)

2.2 不能保证代码块的原子性

https://segmentfault.com/a/1190000016611415

当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i = 2,j = a,合并一下ij = 2a,然后用CAS来操作ij。

2.3 ABA问题

第一个链接中提供了带图的例子,非常容易理解。

简单来说,就是有三个线程,编号为1、2、3,1和2同时查询获取当前值为A,都要修改为B,3查询值为B,要修改为A,执行顺序如下:

  • 1操作成功了,将A修改为B,但2阻塞住了;
  • 此时3查询值为B,成功将B修改为A;
  • 2能运行了,查询当前值为A符合条件,修改为B。

假设1和2是由硬件问题导致的错误重复的取钱操作,那么1和2会被执行两次,会出现不一致的问题。

解决办法:

添加版本号。

真正要做到严谨的CAS机制,在compare阶段不仅要比较期望值A和地址V中的实际值,还要比较变量的版本号是否一致。

那么当1和2在查询时,获取到A值和版本号1,当1修改完后,值为B,版本号为2,当3修改完后值为A,但版本号为3,在2开始执行时判断值虽然一致,但版本号不一致,所以更新失败。

 

posted @ 2022-08-08 23:03  lypbendlf  阅读(38)  评论(0编辑  收藏  举报