竞态条件
Race Condition
高级通用竞态条件(Race Condition)是多个操作交错执行时,结果取决于谁先读、谁先写的问题。理解它能帮你发现并发请求下偶发的数据错误,例如两人同时抢到最后一张优惠券。
你可能会说:「帮我检查多人同时操作时,会不会都以为自己成功了,最后把数据弄错。」
动手看看两人抢最后一张优惠券
1
库里只剩一张券。A点了领取,服务先去查余量,准备确认还有没有券可发。
要点竞态条件是怎么发生的?
- 1
问题藏在读写之间
你先读取库存、判断还有货,再扣减库存,看起来是连贯的一步,实际可能包含多次操作。另一个请求如果在判断和扣减之间读到旧库存,两边就都可能认为自己能下单。
- 2
请求顺序改变结果
竞态条件不要求两个操作在同一瞬间执行,只要执行过程交错,结果就可能不同。所以它常常在本地测试时不出现,却在用户集中操作或任务并行运行时暴露。
- 3
保护关键的共享状态
我们先找出多个请求会共同读写的状态,再让关键判断和修改以可靠的方式完成。比如用数据库的条件更新扣减库存,并检查实际更新了几行,这样做的好处是只有成功扣减的请求会得到成功结果。
容易混淆的地方
并发是多个任务在一段时间内推进,本身不是错误;竞态条件是这些任务的执行顺序影响了本该一致的结果。幂等解决的是同一操作重复执行时如何避免重复产生效果,不会自动阻止两个不同请求争用同一份库存。事务也不是万能开关:保护范围和隔离方式仍要符合具体的读写逻辑。
什么时候用
适合用
- 做限量商品下单时,检查多人同时看到最后一件商品,会不会都提交成功。
- 做账户余额扣减时,检查两个并发请求会不会都按同一笔旧余额计算。
- 做后台任务时,检查多个消费者同时处理同一条待处理记录会不会产生冲突。
不适合用
- 只是把静态页面从一个地址跳到另一个地址,没有共享状态要争用;直接处理路由即可。
- 只是校验单次提交的邮箱格式,结果不依赖其他请求的先后;用数据校验解决。
- 只是网络重试让同一笔支付请求重复到达,先排查重复执行,并用幂等键约束结果。
练一练选一个答案,看看解释
限量优惠券只剩一张,两名用户几乎同时点击领取。你希望最终只有一人成功,哪种处理最可靠?
让 AI 帮你做复制给 AI Agent 直接用
请检查领取优惠券接口是否存在竞态条件:重点看并发请求读取剩余数量、扣减数量和写入领取记录的过程。给出能保证仅一人成功的实现方案,并补充并发测试;说明方案在多实例部署下是否成立。