reentrantlock性能优势取决于正确使用:默认非公平锁更高效,锁粒度要细且unlock必须在finally中,trylock可避免阻塞,condition支持精准唤醒。

ReentrantLock 能实现高性能互斥逻辑,关键不在“用不用”,而在于“怎么用”——它本身不是性能银弹,但配合正确的策略和场景,确实能比 synchronized 更稳、更可控、更可调优。
选对锁模式:非公平锁通常是默认且更高效的选择
ReentrantLock 默认构造是非公平锁(new ReentrantLock()),它允许刚唤醒或新来的线程“插队”获取锁,减少线程上下文切换和挂起开销。在多数高并发、短临界区场景(如计数器更新、缓存读写),非公平锁吞吐量明显更高。
- 仅当出现明显线程饥饿(某些线程长期抢不到锁)时,才考虑公平锁:new ReentrantLock(true)
- 公平锁会维护一个FIFO等待队列,带来额外CAS和链表操作开销,实测在中高竞争下吞吐常下降15%~30%
锁粒度要细,但释放必须可靠
ReentrantLock 是显式锁,lock() 和 unlock() 必须严格配对。性能隐患往往来自错误的锁范围或遗漏释放,而非锁本身。
- 把 lock() 尽量靠近真正需要同步的代码,避免包裹无关IO、网络调用或长耗时计算
- unlock() 必须放在 finally 块中,哪怕只有一行临界代码 —— 这是防止锁泄漏的底线
- 不要在 lock() 后、try 块前做任何可能抛异常的操作,否则可能跳过 try-finally
用 tryLock 避免无效阻塞,提升响应性
当业务能接受“没抢到就换条路走”时,tryLock() 比 blind lock() 更高效。它不挂起线程,不触发调度器介入,CPU利用率更平滑。
- 适合读多写少、乐观更新场景:比如先 tryLock() 修改状态,失败则退化为只读或重试策略
- 搭配超时使用:tryLock(100, TimeUnit.MILLISECONDS) 可防偶发锁持有过久导致级联延迟
- 注意:tryLock 返回 false 不代表出错,而是控制流的一部分,需设计对应分支逻辑
善用 Condition 实现精准唤醒,减少无谓竞争
synchronized 只能用 Object 的 wait/notify,所有等待者共用一个队列;ReentrantLock 支持多个独立 Condition,让不同等待条件各走各的通道。
- 例如生产者-消费者模型中,用 notFull.await() 和 notEmpty.await() 分离两类等待者,避免 notifyAll 唤醒所有线程再筛选
- 每个 Condition 对应一个等待队列,signal() 只唤醒该条件下的线程,显著降低虚假唤醒和竞争概率
- Condition 的 signal() 不会释放锁,唤醒后仍需重新竞争 —— 这是设计使然,不是 bug
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











