- 所有已实现的接口:
Serializable
,ReadWriteLock
ReadWriteLock
的实现支持与 ReentrantLock
相似的语义。
此类具有以下属性:
- 收购订单
此类不强加读者或作者对锁访问的偏好排序。但是,它确实支持可选的 fairness 策略。
- 非公平模式(默认)
- 当构造为非公平(默认)时,读写锁的进入顺序是未指定的,受重入约束的约束。持续争用的非公平锁可能会无限期推迟一个或多个读取器或写入器线程,但通常比公平锁具有更高的吞吐量。
- 公平模式
-
当构建为公平时,线程使用近似到达顺序策略争夺进入。当当前持有的锁被释放时,等待时间最长的单个写线程将被分配写锁,或者如果有一组读线程等待的时间比所有等待的写线程更长,则该组将被分配读锁。
如果写入锁被持有,或者有等待的写入线程,试图获取公平读取锁(不可重入)的线程将被阻塞。直到当前最旧的等待写线程获得并释放写锁后,该线程才会获得读锁。当然,如果一个正在等待的写者放弃等待,留下一个或多个读者线程作为队列中最长的等待者,写锁空闲,那么这些读者将被分配读锁。
尝试获取公平写锁(不可重入)的线程将阻塞,除非读锁和写锁都是空闲的(这意味着没有等待线程)。 (请注意,非阻塞
ReentrantReadWriteLock.ReadLock.tryLock()
和ReentrantReadWriteLock.WriteLock.tryLock()
方法不遵守此公平设置,如果可能,将立即获取锁,而不管等待线程如何。)
- 重入
此锁允许读者和作者以
ReentrantLock
的样式重新获取读或写锁。在释放写入线程持有的所有写入锁之前,不允许非重入读取器。此外,写入者可以获取读锁,但反之则不行。在其他应用程序中,当在读取锁定下执行读取的方法的调用或回调期间持有写入锁定时,重入可能很有用。如果读者试图获取写锁,它将永远不会成功。
- 锁定降级
重入还允许从写锁降级为读锁,方法是获取写锁,然后获取读锁,然后释放写锁。但是,从读锁升级到写锁是not可能的。
- 中断获取锁
读锁和写锁都支持获取锁时中断。
Condition
支持写锁提供了一个
Condition
实现,其行为方式与写锁相同,就像ReentrantLock.newCondition()
提供的Condition
实现对ReentrantLock
所做的一样。当然,Condition
只能与写锁一起使用。读锁不支持
Condition
和readLock().newCondition()
抛出UnsupportedOperationException
。- Instrumentation
此类支持确定锁是持有还是争用的方法。这些方法是为监视系统状态而设计的,而不是为同步控制而设计的。
此类的序列化与内置锁的行为方式相同:反序列化的锁处于解锁状态,而不管其在序列化时的状态如何。
示例用法。这是一个代码草图,展示了如何在更新缓存后执行锁降级(异常处理在以非嵌套方式处理多个锁时特别棘手):
class CachedData {
Object data;
boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
if (!cacheValid) {
data = ...;
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}
try {
use(data);
} finally {
rwl.readLock().unlock();
}
}
}
ReentrantReadWriteLocks 可用于提高某些类型集合的某些使用中的并发性。这通常只有在预期集合很大、由比写入线程更多的读取线程访问并且需要的开销超过同步开销的操作时才值得。例如,这里有一个使用 TreeMap 的类,预计会很大并且会被并发访问。
class RWDictionary {
private final Map<String, Data> m = new TreeMap<>();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();
public Data get(String key) {
r.lock();
try { return m.get(key); }
finally { r.unlock(); }
}
public List<String> allKeys() {
r.lock();
try { return new ArrayList<>(m.keySet()); }
finally { r.unlock(); }
}
public Data put(String key, Data value) {
w.lock();
try { return m.put(key, value); }
finally { w.unlock(); }
}
public void clear() {
w.lock();
try { m.clear(); }
finally { w.unlock(); }
}
}
实现说明
这个锁最多支持65535个递归写锁和65535个读锁。尝试超过这些限制会导致 Error
从锁定方法中抛出。
- 自从:
- 1.5
- 参见:
-
内部类总结
内部类 -
构造方法总结
构造方法构造方法描述创建一个具有默认(非公平)排序属性的新ReentrantReadWriteLock
。ReentrantReadWriteLock
(boolean fair) 使用给定的公平策略创建一个新的ReentrantReadWriteLock
。 -
方法总结
修饰符和类型方法描述protected Thread
getOwner()
返回当前拥有写锁的线程,如果不拥有则返回null
。protected Collection<Thread>
返回一个集合,其中包含可能正在等待获取读锁的线程。protected Collection<Thread>
返回一个集合,其中包含可能正在等待获取读锁或写锁的线程。protected Collection<Thread>
返回一个集合,其中包含可能正在等待获取写锁的线程。final int
返回等待获取读锁或写锁的线程数的估计值。int
查询当前线程持有此锁的可重入读取次数。int
查询为此锁持有的读取锁的数量。protected Collection<Thread>
getWaitingThreads
(Condition condition) 返回一个集合,其中包含那些可能正在等待与写锁关联的给定条件的线程。int
getWaitQueueLength
(Condition condition) 返回等待与写锁关联的给定条件的线程数的估计值。int
查询当前线程持有此锁的可重入写入次数。final boolean
hasQueuedThread
(Thread thread) 查询给定线程是否正在等待获取读锁或写锁。final boolean
查询是否有任何线程正在等待获取读锁或写锁。boolean
hasWaiters
(Condition condition) 查询是否有任何线程正在等待与写锁关联的给定条件。final boolean
isFair()
如果此锁的公平性设置为真,则返回true
。boolean
查询写锁是否被任何线程持有。boolean
查询写锁是否被当前线程持有。readLock()
返回用于读取的锁。toString()
返回标识此锁及其锁定状态的字符串。返回用于写入的锁。
-
构造方法详细信息
-
ReentrantReadWriteLock
public ReentrantReadWriteLock()创建一个具有默认(非公平)排序属性的新ReentrantReadWriteLock
。 -
ReentrantReadWriteLock
public ReentrantReadWriteLock(boolean fair) 使用给定的公平策略创建一个新的ReentrantReadWriteLock
。- 参数:
fair
-true
如果这个锁应该使用公平排序策略
-
-
方法详情
-
writeLock
从接口ReadWriteLock
复制的描述返回用于写入的锁。- 指定者:
writeLock
在接口ReadWriteLock
中- 返回:
- 用于写入的锁
-
readLock
从接口ReadWriteLock
复制的描述返回用于读取的锁。- 指定者:
readLock
在接口ReadWriteLock
中- 返回:
- 用于读取的锁
-
isFair
public final boolean isFair()如果此锁的公平性设置为真,则返回true
。- 返回:
true
如果此锁的公平设置为真
-
getOwner
返回当前拥有写锁的线程,如果不拥有则返回null
。当非所有者的线程调用此方法时,返回值反映当前锁定状态的最大努力近似值。例如,所有者可能暂时是null
,即使有线程试图获取锁但还没有这样做。此方法旨在促进提供更广泛的锁监视功能的子类的构造。- 返回:
-
所有者,或者
null
如果没有
-
getReadLockCount
public int getReadLockCount()查询为此锁持有的读取锁的数量。此方法设计用于监视系统状态,而不用于同步控制。- 返回:
- 持有读锁的数量
-
isWriteLocked
public boolean isWriteLocked()查询写锁是否被任何线程持有。此方法设计用于监视系统状态,而不用于同步控制。- 返回:
true
如果任何线程持有写锁,false
否则
-
isWriteLockedByCurrentThread
public boolean isWriteLockedByCurrentThread()查询写锁是否被当前线程持有。- 返回:
true
如果当前线程持有写锁,false
否则
-
getWriteHoldCount
public int getWriteHoldCount()查询当前线程持有此锁的可重入写入次数。对于与解锁操作不匹配的每个锁定操作,编写器线程都持有一个锁。- 返回:
- 当前线程持有写锁的次数,如果当前线程未持有写锁,则为零
-
getReadHoldCount
public int getReadHoldCount()查询当前线程持有此锁的可重入读取次数。对于与解锁操作不匹配的每个锁定操作,读取器线程都持有一个锁。- 返回:
- 当前线程持有读锁的次数,如果读锁未被当前线程持有则为零
- 自从:
- 1.6
-
getQueuedWriterThreads
返回一个集合,其中包含可能正在等待获取写锁的线程。因为实际的线程集在构造此结果时可能会动态变化,所以返回的集合只是尽力而为的估计。返回集合的元素没有特定的顺序。此方法旨在促进提供更广泛的锁监视功能的子类的构造。- 返回:
- 线程的集合
-
getQueuedReaderThreads
返回一个集合,其中包含可能正在等待获取读锁的线程。因为实际的线程集在构造此结果时可能会动态变化,所以返回的集合只是尽力而为的估计。返回集合的元素没有特定的顺序。此方法旨在促进提供更广泛的锁监视功能的子类的构造。- 返回:
- 线程的集合
-
hasQueuedThreads
public final boolean hasQueuedThreads()查询是否有任何线程正在等待获取读锁或写锁。请注意,因为取消可能随时发生,所以true
返回并不能保证任何其他线程都将获得锁。此方法主要用于监视系统状态。- 返回:
true
如果可能有其他线程在等待获取锁
-
hasQueuedThread
查询给定线程是否正在等待获取读锁或写锁。请注意,因为取消可能随时发生,所以true
返回并不能保证该线程将永远获得锁。此方法主要用于监视系统状态。- 参数:
thread
- 线程- 返回:
true
如果给定的线程正在排队等待这个锁- 抛出:
NullPointerException
- 如果线程为空
-
getQueueLength
public final int getQueueLength()返回等待获取读锁或写锁的线程数的估计值。该值只是一个估计值,因为当此方法遍历内部数据结构时,线程数可能会动态变化。此方法设计用于监视系统状态,而不用于同步控制。- 返回:
- 等待这个锁的估计线程数
-
getQueuedThreads
返回一个集合,其中包含可能正在等待获取读锁或写锁的线程。因为实际的线程集在构造此结果时可能会动态变化,所以返回的集合只是尽力而为的估计。返回集合的元素没有特定的顺序。此方法旨在促进提供更广泛的监视功能的子类的构造。- 返回:
- 线程的集合
-
hasWaiters
查询是否有任何线程正在等待与写锁关联的给定条件。请注意,由于超时和中断可能随时发生,true
返回并不能保证未来的signal
会唤醒任何线程。此方法主要用于监视系统状态。- 参数:
condition
- 条件- 返回:
true
如果有任何等待线程- 抛出:
IllegalMonitorStateException
- 如果这个锁没有被持有IllegalArgumentException
- 如果给定条件与此锁无关NullPointerException
- 如果条件为空
-
getWaitQueueLength
返回等待与写锁关联的给定条件的线程数的估计值。请注意,由于超时和中断随时可能发生,因此估计值仅用作实际等待者数量的上限。此方法设计用于监视系统状态,而不用于同步控制。- 参数:
condition
- 条件- 返回:
- 等待线程的估计数量
- 抛出:
IllegalMonitorStateException
- 如果这个锁没有被持有IllegalArgumentException
- 如果给定条件与此锁无关NullPointerException
- 如果条件为空
-
getWaitingThreads
返回一个集合,其中包含那些可能正在等待与写锁关联的给定条件的线程。因为实际的线程集在构造此结果时可能会动态变化,所以返回的集合只是尽力而为的估计。返回集合的元素没有特定的顺序。此方法旨在促进提供更广泛的状态监视功能的子类的构建。- 参数:
condition
- 条件- 返回:
- 线程的集合
- 抛出:
IllegalMonitorStateException
- 如果这个锁没有被持有IllegalArgumentException
- 如果给定条件与此锁无关NullPointerException
- 如果条件为空
-
toString
返回标识此锁及其锁定状态的字符串。括号中的状态包括字符串"Write locks ="
后跟可重入持有的写锁数,以及字符串"Read locks ="
后跟持有的读锁数。
-