- java.lang.Object
-
- java.util.concurrent.locks.ReentrantReadWriteLock
-
- All Implemented Interfaces:
-
Serializable
,ReadWriteLock
public class ReentrantReadWriteLock extends Object implements ReadWriteLock, Serializable
支持ReadWriteLock
的类似语义ReentrantLock
的实现 。此类具有以下属性:
- 收购令
此类不会强制使用读取器或写入器优先顺序进行锁定访问。 但是,它确实支持可选的公平政策。
- 非公平模式(默认)
- 当被构造为不公平(默认)时,进入读写锁定的顺序是未指定的,受到重入限制。 持续竞争的非空格锁可能无限期地推迟一个或多个读卡器或写入器线程,但通常具有比公平锁定更高的吞吐量。
- 公平模式
-
当公平地构建时,线程使用近似到达订单策略来争取进入。
当释放当前持有的锁时,最长等待的单个写入器线程将被分配写入锁定,或者如果有一组读取器线程等待比所有等待写入器线程长的时间,则该组将被分配读取锁定。
尝试获取公平读锁(不可重入)的线程将阻塞,如果写锁定或有等待的写入程序线程。 直到最旧的当前正在等待的写入程序线程获取并释放写入锁之后,该线程才会获取读锁定。 当然,如果一个等待的作家放弃了等待,留下一个或多个阅读器线程作为队列中最长的服务器,其中写锁定空闲,那么这些读取器将被分配读取锁定。
尝试获取公正的写锁定(非重入)的线程将阻止,除非读锁定和写锁定都是空闲的(这意味着没有等待线程)。 (请注意,非阻塞
ReentrantReadWriteLock.ReadLock.tryLock()
和ReentrantReadWriteLock.WriteLock.tryLock()
方法不符合此公平的设置,如果可能,将立即获取锁定,而不管等待线程)。
- 重入
这个锁允许读者和作者以
ReentrantLock
的风格重新获取读写锁。 在写入线程所持有的所有写入锁已经被释放之前,不允许非重入读取器。另外,写入器可以获取读锁,但反之亦然。 在其他应用程序中,当在执行在读锁定下执行读取的方法的调用或回调期间保留写入锁时,重入可能是有用的。 如果读者尝试获取写入锁定,它将永远不会成功。
- 锁定降级
重入还允许通过获取写入锁定,然后读取锁定然后释放写入锁定从写入锁定到读取锁定。 然而,从读锁定写锁定升级是不可能的。
- 中断锁获取
读取锁定和写入锁定在锁定采集期间都支持中断。
-
Condition
支持写入锁提供了一个
Condition
实现,其行为以同样的方式,相对于写入锁定,为Condition
提供实现ReentrantLock.newCondition()
确实为ReentrantLock
。 这个Condition
当然只能用于写锁。读锁不支持
Condition
和readLock().newCondition()
投掷UnsupportedOperationException
。 - 仪表
该类支持确定锁是否被保持或竞争的方法。 这些方法设计用于监视系统状态,而不是进行同步控制。
此类的序列化与内置锁的操作方式相同:反序列化锁处于未锁定状态,无论其序列化时的状态如何。
示例用法 这是一个代码草图,显示了如何在更新缓存后执行锁定降级(异常处理在以非嵌套方式处理多个锁时尤为棘手):
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(); } } }
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
- 另请参见:
- Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class 描述 static class
ReentrantReadWriteLock.ReadLock
方法readLock()
返回的锁。static class
ReentrantReadWriteLock.WriteLock
方法writeLock()
返回的锁。
-
构造方法摘要
构造方法 Constructor 描述 ReentrantReadWriteLock()
使用默认(非空)订购属性创建新的ReentrantReadWriteLock
。ReentrantReadWriteLock(boolean fair)
创建一个新的ReentrantReadWriteLock
与给定的公平政策。
-
方法摘要
所有方法 接口方法 具体的方法 Modifier and Type 方法 描述 protected Thread
getOwner()
返回当前拥有写锁的线程,如果不拥有,则返回null
。protected Collection<Thread>
getQueuedReaderThreads()
返回一个包含可能正在等待获取读取锁的线程的集合。protected Collection<Thread>
getQueuedThreads()
返回一个包含可能正在等待获取读取或写入锁定的线程的集合。protected Collection<Thread>
getQueuedWriterThreads()
返回一个包含可能正在等待获取写入锁的线程的集合。int
getQueueLength()
返回等待获取读取或写入锁定的线程数的估计。int
getReadHoldCount()
查询当前线程对此锁的可重入读取保留数。int
getReadLockCount()
查询为此锁持有的读取锁的数量。protected Collection<Thread>
getWaitingThreads(Condition condition)
返回包含可能在与写锁相关联的给定条件下等待的线程的集合。int
getWaitQueueLength(Condition condition)
返回与写入锁相关联的给定条件等待的线程数的估计。int
getWriteHoldCount()
查询当前线程对此锁的可重入写入数量。boolean
hasQueuedThread(Thread thread)
查询给定线程是否等待获取读取或写入锁定。boolean
hasQueuedThreads()
查询是否有任何线程正在等待获取读取或写入锁定。boolean
hasWaiters(Condition condition)
查询任何线程是否等待与写锁相关联的给定条件。boolean
isFair()
如果此锁的公平设置为true,则返回true
。boolean
isWriteLocked()
查询写锁是否由任何线程持有。boolean
isWriteLockedByCurrentThread()
查询写锁是否由当前线程持有。ReentrantReadWriteLock.ReadLock
readLock()
返回用于阅读的锁。String
toString()
返回一个标识此锁的字符串以及其锁定状态。ReentrantReadWriteLock.WriteLock
writeLock()
返回用于写入的锁。
-
-
-
方法详细信息
-
writeLock
public ReentrantReadWriteLock.WriteLock writeLock()
描述从接口ReadWriteLock
复制返回用于写入的锁。- Specified by:
-
writeLock
在接口ReadWriteLock
- 结果
- 用于书写的锁
-
readLock
public ReentrantReadWriteLock.ReadLock readLock()
描述从接口ReadWriteLock
复制返回用于阅读的锁。- Specified by:
-
readLock
在接口ReadWriteLock
- 结果
- 用于阅读的锁
-
isFair
public final boolean isFair()
如果此锁的公平设置为true,则返回true
。- 结果
-
true
如果这个锁的公平设置为true
-
getOwner
protected Thread 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
protected Collection<Thread> getQueuedWriterThreads()
返回一个包含可能正在等待获取写入锁的线程的集合。 因为在构建此结果时,实际的线程集可能会动态更改,所以返回的集合只是尽力而为的估计。 返回的集合的元素没有特定的顺序。 该方法旨在便于构建提供更广泛的锁定监控设施的子类。- 结果
- 线程的收集
-
getQueuedReaderThreads
protected Collection<Thread> getQueuedReaderThreads()
返回一个包含可能正在等待获取读取锁的线程的集合。 因为在构建此结果时,实际的线程集可能会动态更改,所以返回的集合只是尽力而为的估计。 返回的集合的元素没有特定的顺序。 该方法旨在便于构建提供更广泛的锁定监控设施的子类。- 结果
- 线程的收集
-
hasQueuedThreads
public final boolean hasQueuedThreads()
查询是否有任何线程正在等待获取读取或写入锁定。 请注意,由于取消可能随时发生,因此true
返回不能保证任何其他线程将获得锁定。 该方法主要用于监视系统状态。- 结果
-
true
如果可能有其他线程等待获取锁
-
hasQueuedThread
public final boolean hasQueuedThread(Thread thread)
查询给定线程是否等待获取读取或写入锁定。 请注意,由于取消可能随时发生,因此true
返回不能保证此线程将获取锁定。 该方法主要用于监视系统状态。- 参数
-
thread
- 线程 - 结果
-
true
如果给定的线程排队等待这个锁 - 异常
-
NullPointerException
- 如果线程为空
-
getQueueLength
public final int getQueueLength()
返回等待获取读取或写入锁定的线程数的估计。 该值只是一个估计,因为线程数可能会在此方法遍历内部数据结构时动态更改。 该方法设计用于监控系统状态,不用于同步控制。- 结果
- 估计等待这个锁的线程数
-
getQueuedThreads
protected Collection<Thread> getQueuedThreads()
返回一个包含可能正在等待获取读取或写入锁定的线程的集合。 因为在构建此结果时,实际的线程集可能会动态更改,所以返回的集合只是尽力而为的估计。 返回的集合的元素没有特定的顺序。 该方法旨在便于构建提供更广泛监控设施的子类。- 结果
- 线程的收集
-
hasWaiters
public boolean hasWaiters(Condition condition)
查询任何线程是否等待与写锁相关联的给定条件。 请注意,由于超时和中断可能随时发生,因此true
返回不能保证未来的signal
将唤醒任何线程。 该方法主要用于监视系统状态。- 参数
-
condition
- 条件 - 结果
-
true
如果有任何等待线程 - 异常
-
IllegalMonitorStateException
- 如果此锁没有保持 -
IllegalArgumentException
- 如果给定的条件不与此锁相关联 -
NullPointerException
- 如果条件为空
-
getWaitQueueLength
public int getWaitQueueLength(Condition condition)
返回与写入锁相关联的给定条件等待的线程数的估计。 请注意,由于超时和中断可能在任何时间发生,估计仅作为实际服务员人数的上限。 该方法设计用于监视系统状态,不用于同步控制。- 参数
-
condition
- 条件 - 结果
- 估计等待线程数
- 异常
-
IllegalMonitorStateException
- 如果此锁不保持 -
IllegalArgumentException
- 如果给定的条件不与此锁相关联 -
NullPointerException
- 如果条件为空
-
getWaitingThreads
protected Collection<Thread> getWaitingThreads(Condition condition)
返回包含可能在与写锁相关联的给定条件下等待的线程的集合。 因为在构建此结果时,实际的线程集可能会动态更改,所以返回的集合只是尽力而为的估计。 返回的集合的元素没有特定的顺序。 该方法旨在便于构建提供更广泛的状态监测设施的子类。- 参数
-
condition
- 条件 - 结果
- 线程的收集
- 异常
-
IllegalMonitorStateException
- 如果此锁没有保持 -
IllegalArgumentException
- 如果给定的条件不与此锁相关联 -
NullPointerException
- 如果条件为空
-
-