昨天一个帖子说道了 CAS 和 ABA,有个问题纠结一天了请教下各位大佬。
我的理解是:ABA 问题无非就是库存从 10 变成 11 又变回 10 ,虽然后面的 10 已经不是我第一次查到的 10 了,但是库存无非就是个数字,只要库存数量合规合法直接扣不就好了
所以如果不做预防措施会出现什么问题吗
1
ipwx 2022-01-06 17:42:37 +08:00 1
我觉得你对 CAS 锁的应用场景有些误区。库存这已经牵扯到业务数据库了,和 CAS 锁没有任何关系。
要理解 CAS 中 ABA 的棘手难题,非得写几段 C++ 程序才有感觉。。。。这也是我为啥总是觉得学习东西不能用类比,用库存这种概念去理解高并发无锁的算法,总是不得要领。 |
2
ipwx 2022-01-06 17:43:57 +08:00
ummm 想了想好像用在库存这种场景下倒也不是不可能。。。?
|
3
wolfie 2022-01-06 17:48:27 +08:00 1
一直有个 modified_count 作为版本号,什么情况下会 ABA 。
|
4
partystart 2022-01-06 17:55:30 +08:00 1
所以有的 http 或者 rpc 接口会要求你提供一个幂等标识过去啊
|
5
Chinsung 2022-01-06 17:58:35 +08:00 1
个人感觉是 CAS 仅限于非常原子的操作,对上下文无依赖的那种。
比如说,你前置条件是该商品上架状态才可以去减库存,此时你 CAS 保证了减库存,但不能保证自旋后之前的状态校验是正确的(当然你也可以加大自选范围,不过这样 CAS 也没什么优势了)。而锁可以保证。 锁的底层一般也是依赖 CAS 去获取的 |
6
zeni123 2022-01-06 20:20:48 +08:00 1
数据库的乐观锁也是用了类似 CAS 的实现 但是比 Java 里面的锁要复杂一下
防止 ABA 只要加上版本号就可以 10v1.0 -> 11v1.1 -> 10v1.2 .... 当然数据库用的是 MVCC 和 Java 里的不是太一样 |
7
danieladu 2022-01-07 09:46:33 +08:00 1
CAS ,ABA , 包括数据库事务,都不是一个概念呀,防止 ABA ,就是在每次修改数据的时候,数据库记录 一个 tag (针对本次的修改),下次需要更新就检查带过来的 tag 和数据库的 tag 一致不一致,不一致说明中间已经被人修改了,就会拒绝本次更改。
涉及到业务层就更加多样了。有些事直接返回用户错误,有些是传入一个委托,tag 不一致的时候重新获取一份新的数据,在这上面进行修改,等等等等。 |
8
qiany 2022-01-07 10:02:40 +08:00 1
这个和 countdownlatch 有点像 应该没啥问题
|
9
exch4nge 2022-01-07 10:22:20 +08:00 via iPhone 1
仅算库存数量场景没问题。有问题的场景是 CAS 的变量相关的东西发生改变。比如你还维护了这十个库存商品的唯一序列号之类的。实际场景下大部分 CAS 的是指针,指针没变但是由于内存分配器又复用了刚释放的位置,新分配的对象还是在一样的指针上,但是对象内容跟之前老的指针完全不一样
|
10
exch4nge 2022-01-07 10:26:23 +08:00 via iPhone 1
我还以为是原子操作 CAS ,是数据库 CAS ?不过都差不多
|
11
qingshuang 2022-01-07 10:53:57 +08:00 1
不是什么场景都要预防 ABA 问题的,扣减库存这种显然不用管 ABA 问题。
如果有个接口需要判断库存是否发生过扣减,扣减了多少。这种情况需要考虑版本号 |
12
Canon1014 OP 感谢各位的帮助,突然的开发任务没有及时回复表示抱歉 🙁
|