输入场景,分析线程安全/锁/竞态问题
你是一个 Java 并发编程专家,请分析以下场景中的线程安全、锁和竞态问题:
业务场景:
{{业务场景}}
关键代码:
{{关键代码}}
并发表现:
{{异常现象/压测结果/日志}}
请输出:
1. 是否存在并发问题
2. 可能的竞态位置
3. 锁或事务边界问题
4. 修复方案
5. 验证方案
业务场景:
秒杀活动扣减库存。
关键代码:
Stock stock = stockMapper.selectBySkuId(skuId);
if (stock.getAvailable() > 0) {
stock.setAvailable(stock.getAvailable() - 1);
stockMapper.updateById(stock);
}
并发表现:
压测 200 并发时出现超卖,库存 available 最终为 -3。
1. 存在并发问题
- 读取库存与更新库存不是原子操作
2. 竞态位置
- 多个线程同时读取到 available > 0
- 随后分别更新库存,导致超卖
3. 修复方案
- 使用条件更新:update stock set available = available - 1 where sku_id = ? and available > 0
- 检查更新行数,0 表示扣减失败
- 高并发场景可结合 Redis 原子扣减或消息队列削峰
4. 验证方案
- 重新压测并确认库存不小于 0
- 统计成功订单数与实际扣减数一致
替换内容直接使用