高并发场景下使用 CAS 锁库存,不预防 ABA 会怎么样

2022-01-06 17:32:04 +08:00
 Canon1014

昨天一个帖子说道了 CAS 和 ABA,有个问题纠结一天了请教下各位大佬。

我的理解是:ABA 问题无非就是库存从 10 变成 11 又变回 10 ,虽然后面的 10 已经不是我第一次查到的 10 了,但是库存无非就是个数字,只要库存数量合规合法直接扣不就好了

所以如果不做预防措施会出现什么问题吗

2239 次点击
所在节点    程序员
12 条回复
ipwx
2022-01-06 17:42:37 +08:00
我觉得你对 CAS 锁的应用场景有些误区。库存这已经牵扯到业务数据库了,和 CAS 锁没有任何关系。

要理解 CAS 中 ABA 的棘手难题,非得写几段 C++ 程序才有感觉。。。。这也是我为啥总是觉得学习东西不能用类比,用库存这种概念去理解高并发无锁的算法,总是不得要领。
ipwx
2022-01-06 17:43:57 +08:00
ummm 想了想好像用在库存这种场景下倒也不是不可能。。。?
wolfie
2022-01-06 17:48:27 +08:00
一直有个 modified_count 作为版本号,什么情况下会 ABA 。
partystart
2022-01-06 17:55:30 +08:00
所以有的 http 或者 rpc 接口会要求你提供一个幂等标识过去啊
Chinsung
2022-01-06 17:58:35 +08:00
个人感觉是 CAS 仅限于非常原子的操作,对上下文无依赖的那种。
比如说,你前置条件是该商品上架状态才可以去减库存,此时你 CAS 保证了减库存,但不能保证自旋后之前的状态校验是正确的(当然你也可以加大自选范围,不过这样 CAS 也没什么优势了)。而锁可以保证。
锁的底层一般也是依赖 CAS 去获取的
zeni123
2022-01-06 20:20:48 +08:00
数据库的乐观锁也是用了类似 CAS 的实现 但是比 Java 里面的锁要复杂一下

防止 ABA 只要加上版本号就可以 10v1.0 -> 11v1.1 -> 10v1.2 ....

当然数据库用的是 MVCC 和 Java 里的不是太一样
danieladu
2022-01-07 09:46:33 +08:00
CAS ,ABA , 包括数据库事务,都不是一个概念呀,防止 ABA ,就是在每次修改数据的时候,数据库记录 一个 tag (针对本次的修改),下次需要更新就检查带过来的 tag 和数据库的 tag 一致不一致,不一致说明中间已经被人修改了,就会拒绝本次更改。
涉及到业务层就更加多样了。有些事直接返回用户错误,有些是传入一个委托,tag 不一致的时候重新获取一份新的数据,在这上面进行修改,等等等等。
qiany
2022-01-07 10:02:40 +08:00
这个和 countdownlatch 有点像 应该没啥问题
exch4nge
2022-01-07 10:22:20 +08:00
仅算库存数量场景没问题。有问题的场景是 CAS 的变量相关的东西发生改变。比如你还维护了这十个库存商品的唯一序列号之类的。实际场景下大部分 CAS 的是指针,指针没变但是由于内存分配器又复用了刚释放的位置,新分配的对象还是在一样的指针上,但是对象内容跟之前老的指针完全不一样
exch4nge
2022-01-07 10:26:23 +08:00
我还以为是原子操作 CAS ,是数据库 CAS ?不过都差不多
qingshuang
2022-01-07 10:53:57 +08:00
不是什么场景都要预防 ABA 问题的,扣减库存这种显然不用管 ABA 问题。
如果有个接口需要判断库存是否发生过扣减,扣减了多少。这种情况需要考虑版本号
Canon1014
2022-01-08 16:59:09 +08:00
感谢各位的帮助,突然的开发任务没有及时回复表示抱歉 🙁

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/826638

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX