引言
在多线程编程中,锁机制是确保线程安全的核心工具之一。Java 提供了两种锁机制:隐式锁 synchronized
和显式锁 ReentrantLock
。ReentrantLock
以其灵活性、高性能和丰富的功能,成为复杂并发场景的首选工具。
本文将从设计思想、底层实现、常见问题到最佳实践,深入解析 ReentrantLock
的工作原理,并揭示其依赖的核心框架 AQS(AbstractQueuedSynchronizer) 。
一、设计思想:为什么选择 ReentrantLock?
1. 显式锁 vs 隐式锁
-
synchronized
的局限性:- 锁的获取与释放由 JVM 隐式管理,无法灵活控制(如超时、中断)。
- 仅支持单一条件变量(通过
wait()
和notify()
),难以实现多条件等待(如生产者-消费者模型)。
-
ReentrantLock
的优势:-
开发者手动调用
lock()
和unlock()
,结合try-finally
确保锁释放。 -
提供更细粒度的控制能力:
- 可中断:通过
lockInterruptibly()
响应中断。 - 超时机制:通过
tryLock(5, TimeUnit.SECONDS)
避免死锁。 - 公平性策略:支持按线程请求顺序分配锁(减少饥饿问题)。
- 可中断:通过
-
2. 可重入性(Reentrancy)
-
问题场景:
public void recursiveMethod() { lock.lock(); try { if (condition) recursiveMethod(); // 递归调用 } finally { lock.unlock(