JJava 知识库
JAVA INTERVIEW

高频面试题

Java多线程进阶约 2 分钟

高并发扣减同一个商品库存时,你会用 synchronized 还是 ReentrantLock?锁粒度怎么定?

参考回答约 2 分钟 · 口语表达
我的判断

库存扣减优先让数据库或库存服务做条件更新;JVM 锁只对单实例有效,选 synchronized 还是 ReentrantLock 反而是第二层问题。

如果多台应用同时扣同一个商品,本机锁挡不住其他实例。我会把正确性落在库存存储上,例如:

UPDATE sku_stock
SET available = available - 1
WHERE sku_id = ? AND available > 0;

根据受影响行数判断是否成功,并用业务请求号做幂等。热点很高时再通过分桶、排队或 Redis 预扣降低数据库竞争。

单进程内如果确实要保护共享对象,临界区短且只需要互斥,我会用 synchronized,语义简单、释放锁不容易写错;需要可中断、超时尝试或多个 Condition 时才用 ReentrantLock,并严格在 finally 解锁。

锁粒度通常按 skuId 做固定数量的条带,而不是每个商品永久创建一把锁,也不是锁整个扣库存方法。最终用热点商品压测观察等待时间、失败率和吞吐,不只验证库存没有负数。

思路拆解问题分析

这题容易一开始就在两种 Java 锁之间选边,但实际约束是 库存状态在哪里、是否多实例、失败是否会重试。锁只解决互斥,幂等、持久化和跨进程正确性必须另行处理。