ReentrantLock 通过可重入性、公平性选择、tryLock 超时机制和 Condition 精准唤醒,比 synchronized 更灵活可控;需严格配对 lock/unlock、避免盲目重试、正确使用 await/signal。

ReentrantLock 能比 synchronized 更精准、更可控地保护数据更新逻辑,尤其适合高并发、读多写少或需要响应中断的场景。关键不在于“换掉 synchronized”,而在于根据实际需求选择它的特性来解决问题。
用可重入性避免递归死锁
当更新逻辑嵌套调用(比如 update() 内部调用 validate(),而后者也需加锁)时,synchronized 和 ReentrantLock 都支持可重入,但 ReentrantLock 的显式控制更清晰。同一线程重复 lock() 不会阻塞,计数器自动累加;对应次数的 unlock() 后才真正释放锁。
- 确保每次 lock() 都配对 finally 中的 unlock(),否则极易导致死锁
- 避免在 try 块外调用 lock(),防止未获取锁就进入 finally 执行 unlock() 报 IllegalMonitorStateException
按需选择公平性与性能平衡
默认非公平锁吞吐更高,适合大多数业务更新场景(如订单扣减、库存修改),新线程可能“插队”成功,减少上下文切换开销;公平锁则严格按等待顺序分配,适合对响应时间敏感、不能容忍长等待的系统(如金融类实时风控)。
- 创建公平锁:new ReentrantLock(true)
- 非公平锁是默认行为,无需额外参数,性能通常更优
- 公平性只影响等待队列调度,不影响锁的可重入或线程安全性
用 tryLock 避免无限阻塞
在更新前先尝试获取锁,超时即放弃或降级处理,比无条件等待更健壮。例如库存扣减失败时,可返回“库存紧张”而非让用户长时间等待。
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:if (lock.tryLock(3, TimeUnit.SECONDS)) { ... } else { /* 降级逻辑 */ }
- 注意:tryLock 在等待期间可被中断,若需响应中断,应捕获 InterruptedException
- 不要在循环中盲目重试 tryLock,需加入退避策略或限流控制
搭配 Condition 实现精准唤醒
相比 synchronized + notifyAll() 的“广播式唤醒”,Condition 可为不同等待条件(如“库存充足”“余额足够”)创建独立等待队列,更新完成后只唤醒关心该条件的线程,减少无效调度。
- 一个 ReentrantLock 可关联多个 Condition,例如 lock.newCondition()
- 更新成功后调用 signal() 或 signalAll(),而不是 notify()/notifyAll()
- await() 必须在 lock 持有状态下调用,且需在 try-finally 中确保 unlock()
不复杂但容易忽略——真正起作用的不是锁本身,而是你如何把它嵌入业务流程里。


















