ReentrantLock
提供了两种不同的实现类来支持锁的公平性和非公平性:ReentrantLock.NonfairSync
和 ReentrantLock.FairSync
。
1. 非公平锁实现(NonfairSync
):
ReentrantLock
默认采用非公平锁实现。在非公平锁的实现中,当一个线程尝试获取锁时,会直接尝试获取,而不管其他线程是否在等待队列中等待锁。
// ReentrantLock 的非公平锁实现
static final class NonfairSync extends Sync {
// ...
}
2. 公平锁实现(FairSync
):
公平锁的实现考虑了等待时间较长的线程,优先让等待时间最长的线程获取锁。在公平锁的实现中,当一个线程尝试获取锁时,会先查看等待队列中是否有等待的线程,如果有,则按照等待时间的先后顺序,依次尝试获取锁。
// ReentrantLock 的公平锁实现
static final class FairSync extends Sync {
// ...
}
公平性和非公平性的选择:
- 非公平锁(默认):
- 通过
ReentrantLock
构造函数创建的锁默认是非公平锁。 - 非公平锁的优点是可以提高吞吐量,因为它允许新请求直接插队而不必等待。
- 缺点是可能会导致某些线程饥饿,长时间等待的线程可能永远无法获取锁。
- 通过
ReentrantLock lock = new ReentrantLock(); // 非公平锁
- 公平锁:
- 通过指定
true
参数,可以创建一个公平锁。 - 公平锁的优点是可以避免线程饥饿,保证所有等待线程都有机会获取锁。
- 缺点是可能会降低吞吐量,因为线程必须等待更长的时间才能获取锁。
- 通过指定
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
在使用 ReentrantLock
时,可以根据应用场景和性能需求选择公平锁或非公平锁。默认情况下,由于非公平锁的性能更好,因此在不特别需要公平性的情况下,通常使用默认的非公平锁即可。