ReentrantLock 是 Java 中基于 AQS (AbstractQueuedSynchronizer) 实现的一个可重入互斥锁。以下是其主要实现原理:
核心组件
- AQS (AbstractQueuedSynchronizer)
- 提供了同步状态的原子性管理
- 维护一个 FIFO 的等待队列
- 实现了线程的阻塞和唤醒机制
- Sync 内部类
- ReentrantLock 的核心同步器,继承自 AQS
- 有公平(FairSync)和非公平(NonfairSync)两种实现
关键实现机制
1. 可重入性实现
- 通过一个计数器
state
记录重入次数 - 线程第一次获取锁时,
state
从 0 变为 1 - 同一线程再次获取锁时,
state
递增 - 释放锁时
state
递减,直到为 0 时完全释放
2. 公平锁与非公平锁
- 非公平锁 (默认)
- 新线程可以直接尝试获取锁,可能插队
- 性能更高,但可能导致线程饥饿
- 公平锁
- 严格按照 FIFO 顺序获取锁
- 新线程必须加入队列尾部等待
3. 锁获取流程
// 非公平锁获取示例
final void lock() {
if (compareAndSetState(0, 1)) // 先尝试直接获取
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1); // 调用AQS的acquire方法
}
4. 锁释放流程
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
与 synchronized 的区别
- API 层面
- ReentrantLock 是显式锁,需要手动加锁解锁
- synchronized 是隐式锁,自动管理
- 功能特性
- ReentrantLock 支持公平锁、可中断、超时等待、条件变量等
- synchronized 不支持这些高级特性
- 性能
- 在 Java 6 及以后版本中,两者性能接近
- 高竞争情况下 ReentrantLock 可能表现更好
- 实现层面
- synchronized 是 JVM 内置实现,基于 monitor 机制
- ReentrantLock 是 JDK 代码实现,基于 AQS
ReentrantLock 的这种实现方式使其比 synchronized 更加灵活,但也需要开发者更小心地管理锁的获取和释放,通常需要在 finally 块中确保锁被释放。