ReentrantLock
是 Java 中提供的一种可重入锁(也称为递归锁),它提供了比内置的synchronized
关键字更灵活的锁机制。下面详细介绍 ReentrantLock
的多种用法以及适用的场景:
1、基本用法:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
public void doSomething() {
lock.lock(); // 获取锁
try {
// 临界区代码
} finally {
lock.unlock(); // 释放锁
}
}
}
2、 公平锁与非公平锁
ReentrantLock fairLock = new ReentrantLock(true); // 创建公平锁
ReentrantLock unfairLock = new ReentrantLock(); // 创建非公平锁
公平锁:按照请求锁的顺序依次获取锁,不会产生饥饿现象。适用于对线程执行顺序有严格要求的场景。
非公平锁:允许某些线程插队,有可能会导致部分线程长时间无法获取锁。适用于性能要求较高的场景。
3. 锁的获取与释放
ReentrantLock lock = new ReentrantLock();
// 尝试获取锁,立即返回结果,不会阻塞
boolean tryLock = lock.tryLock();
// 尝试获取锁,等待指定的时间,超时返回结果
boolean tryLockWithTimeout = lock.tryLock(1000, TimeUnit.MILLISECONDS);
// 释放锁
lock.unlock();
4. 条件变量
java
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// 在条件满足时等待
lock.lock();
try {
while (!conditionMet()) {
condition.await(); // 等待条件满足
}
// 条件满足后执行操作
} finally {
lock.unlock();
}
// 条件变量发生变化时通知等待的线程
lock.lock();
try {
updateCondition();
condition.signalAll(); // 唤醒所有等待的线程
} finally {
lock.unlock();
}
5. 使用场景
- 需要更灵活的锁控制:
ReentrantLock
提供了更多的锁控制方法,比如tryLock()
、tryLock(long timeout, TimeUnit unit)
,适用于需要更灵活控制的场景。 - 需要避免死锁:
ReentrantLock
支持公平锁和非公平锁,可以避免某些死锁情况的发生。 - 需要实现读写分离:
ReentrantLock
可以灵活控制读线程和写线程的访问顺序,适用于读写分离的场景。 - 需要实现特定的等待通知机制:通过
Condition
接口可以实现特定条件下的等待和通知机制,适用于复杂的线程协作场景。
总之,ReentrantLock
提供了比内置锁更加灵活和强大的锁机制,适用于对并发控制有较高要求的场景,如高并发、读写分离、死锁避免等。