优先选用synchronized,因其语法简洁、自动释放锁、不易出错;仅在需要可中断获取、超时等待、公平锁或多条件变量等高级功能时才使用ReentrantLock。

选 synchronized 还是 ReentrantLock,关键看你要不要那几项“高级控制权”。日常开发中,synchronized 更安全、更省心;只有当你明确需要中断响应、超时等待、公平调度或多条件唤醒时,才该切到 ReentrantLock。
synchronized 适合什么场景
它是最轻量、最稳妥的同步方案,适用于绝大多数基础同步需求:
- 临界区代码短、竞争不激烈(比如计数器增减、状态标记更新)
- 不需要在获取锁时做超时或中断处理
- 不涉及多个逻辑条件的等待/唤醒(例如不能同时管理“库存空”和“库存满”两个等待队列)
- 团队对并发编程经验有限,希望降低出错概率——synchronized 不会因漏写 unlock 而死锁
ReentrantLock 解决哪些 synchronized 做不到的事
它的价值不在“替代”,而在“补位”。以下功能是 synchronized 完全不具备的:
- 可中断获取锁:调用 lockInterruptibly() 后,线程被阻塞时仍能响应 interrupt(),适合有取消语义的任务(如用户主动取消下单)
- 带超时的锁尝试:tryLock(3, TimeUnit.SECONDS) 可避免无限等待,提升系统响应性与容错能力
- 显式公平策略:new ReentrantLock(true) 按请求顺序分配锁,防止个别线程长期饥饿(注意:吞吐量通常下降 10%–20%)
- 多条件变量支持:一个锁可创建多个 Condition(如 conditionEmpty、conditionFull),精准唤醒对应等待组,比 wait/notify 更可控
性能和维护成本怎么权衡
从 JDK 15 开始,synchronized 已移除偏向锁,轻量级锁和重量级锁路径高度优化。在多数实际业务中(非极端高争用),两者性能差异微乎其微:
立即学习“Java免费学习笔记(深入)”;
- 低争用(
- 高争用(百级线程抢同一把锁):ReentrantLock 的 AQS 队列管理更稳定,避免大量自旋浪费 CPU
- 维护风险:ReentrantLock 必须在 finally 中 unlock,漏写即导致死锁;synchronized 由 JVM 保证释放,异常也不影响
一句话选择建议
优先用 synchronized;当你的日志里开始出现“线程卡在 lock() 无法唤醒”“想让超时订单自动回滚”“生产者消费者总唤醒错队列”这类问题时,再引入 ReentrantLock 并明确使用它的某一项特有能力。


















