Lock 接口与 ReentrantLock
Lock 接口提供了比 synchronized 更灵活的锁机制,ReentrantLock 是其最常用的实现。
Lock 接口核心方法
Java
public interface Lock {
void lock(); // 获取锁
void lockInterruptibly(); // 可中断获取锁
boolean tryLock(); // 尝试获取锁,立即返回
boolean tryLock(long time, TimeUnit unit); // 超时尝试获取锁
void unlock(); // 释放锁
Condition newCondition(); // 创建条件变量
}
ReentrantLock 基本用法
Java
private final ReentrantLock lock = new ReentrantLock();
public void method() {
lock.lock(); // 获取锁
try {
// 同步代码
} finally {
lock.unlock(); // 必须在 finally 中释放锁
}
}
重要:必须在 try-finally 中释放锁,避免异常导致锁未释放。
ReentrantLock 特性
公平锁与非公平锁
Java
// 非公平锁(默认,性能更高)
ReentrantLock lock = new ReentrantLock();
// 公平锁(按等待顺序获取)
ReentrantLock lock = new ReentrantLock(true);
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 非公平锁 | 性能高,可能饥饿 | 一般场景 |
| 公平锁 | 按顺序获取,性能低 | 需要公平性 |
可中断锁
Java
try {
lock.lockInterruptibly(); // 可被 interrupt 中断等待
// 同步代码
} catch (InterruptedException e) {
// 处理中断
} finally {
lock.unlock();
}
超时获取锁
Java
if (lock.tryLock(3, TimeUnit.SECONDS)) { // 等待3秒
try {
// 获取成功,执行同步代码
} finally {
lock.unlock();
}
} else {
// 获取失败,执行其他逻辑
}
Condition 条件变量
Java
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void await() throws InterruptedException {
lock.lock();
try {
condition.await(); // 等待条件
} finally {
lock.unlock();
}
}
public void signal() {
lock.lock();
try {
condition.signal(); // 唤醒等待线程
} finally {
lock.unlock();
}
}
ReentrantLock vs synchronized
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 锁获取释放 | 自动 | 手动 unlock |
| 公平锁 | ❌ 不支持 | ✅ 支持 |
| 可中断 | ❌ 不支持 | ✅ 支持 |
| 超时获取 | ❌ 不支持 | ✅ 支持 |
| 条件变量 | 单个(wait/notify) | 多个(Condition) |
| 性能 | JDK 6 后差距小 | 略有优势 |
要点总结
- ReentrantLock 必须手动 unlock,在 finally 中释放
- 支持公平锁和非公平锁,默认非公平
- 支持可中断获取锁:lockInterruptibly()
- 支持超时获取锁:tryLock(time)
- 支持多个 Condition 条件变量
- 功能比 synchronized 强,但使用复杂
- 优先使用 synchronized,需要高级功能才用 ReentrantLock
📝 发现内容有误?点击此处直接编辑