在Java并发编程中,ReentrantLock
是一个功能强大的同步工具,它提供了比 synchronized
关键字更为丰富的功能。ReentrantLock
是 java.util.concurrent.locks
包中的一个类,它允许完全的轮询和定时锁等候,以及可中断的锁定和尝试(非阻塞)锁定。通过使用 ReentrantLock
,我们可以实现更复杂的线程同步策略,提高程序的性能和灵活性。本文将深入探讨 ReentrantLock
的使用,并通过示例来演示如何利用它来实现高级锁功能。
ReentrantLock 简介
ReentrantLock
是一种可重入互斥锁,它拥有与 synchronized
相同的基本行为和语义,但功能更加强大。其特点包括:
- 可响应性:锁可以由未持有锁的线程释放,这减少了锁不必要的保持时间。
- 可中断性:一个正在等待锁的线程可以被中断。
- 公平性:锁可以设置为公平锁或非公平锁。
- 条件变量:
ReentrantLock
配合Condition
接口提供了比Object
的wait()
、notify()
和notifyAll()
方法更强大的等待/通知机制。
使用 ReentrantLock
创建和使用
创建一个 ReentrantLock
对象非常简单:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
public void performTask() {
lock.lock(); // 获取锁
try {
// 执行临界区代码
} finally {
lock.unlock(); // 释放锁
}
}
}
在上面的例子中,我们首先创建了一个 ReentrantLock
对象。然后,在 performTask
方法中,使用 lock()
方法获取锁,并在 finally
块中使用 unlock()
方法释放锁,以确保锁最终会被释放。
公平性和非公平性
ReentrantLock
可以配置为公平锁或非公平锁。公平锁意味着等待时间最长的线程会先获得锁。这对于避免线程饥饿很有用,但可能会牺牲一些性能。默认情况下,ReentrantLock
是非公平的。
// 创建一个公平的 ReentrantLock
ReentrantLock fairLock = new ReentrantLock(true);
可中断的锁定
与 synchronized
不同,ReentrantLock
允许线程在等待锁时被中断。这提供了一种避免死锁的策略。
lock.lockInterruptibly(); // 可以被中断的锁定
尝试锁定
tryLock()
方法尝试立即获得锁,如果成功则返回 true
,否则返回 false
。这种非阻塞的方式对于减少等待时间和提高响应性非常有用。
if (lock.tryLock()) {
try {
// 执行临界区代码
} finally {
lock.unlock();
}
} else {
// 无法获得锁,采取其他行动
}
条件变量
与 synchronized
配合 Object
的 wait()
、notify()
和 notifyAll()
不同,ReentrantLock
使用 Condition
接口来实现更灵活的等待/通知模式。
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (/* 条件不满足 */) {
condition.await(); // 等待条件成立
}
// 执行临界区代码
} finally {
lock.unlock();
}
在上面的代码中,我们首先创建了 ReentrantLock
和相关的 Condition
对象。当某个条件不满足时,线程可以在 condition.await()
上等待,直到其他线程调用 condition.signal()
或 condition.signalAll()
方法。
结论
ReentrantLock
提供了比 synchronized
更加丰富和灵活的线程同步机制。通过使用 ReentrantLock
,开发者可以更好地控制锁的行为,实现公平性、可中断性、尝试锁定和非阻塞等待等功能。这些高级特性使得 ReentrantLock
成为构建高性能并发应用程序的强有力工具。然而,使用 ReentrantLock
需要谨慎,因为它比 synchronized
更容易出错,特别是在涉及多个条件变量时。正确使用 ReentrantLock
要求对其底层原理有深入的理解,并且能够识别适合使用高级锁功能的场景。