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; volatile 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<String, Data>(); 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 String[] allKeys() { r.lock(); try { return m.keySet().toArray(); } 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
从锁定方法抛出。
Modifier and Type | Class and Description |
---|---|
static class |
ReentrantReadWriteLock.ReadLock
该锁由方法
readLock() 返回。
|
static class |
ReentrantReadWriteLock.WriteLock
该锁由方法
writeLock() 返回。
|
Constructor and Description |
---|
ReentrantReadWriteLock()
创建一个新的
ReentrantReadWriteLock 与默认(非空)订购属性。
|
ReentrantReadWriteLock(boolean fair)
创建一个新的
ReentrantReadWriteLock 与给定的公平政策。
|
Modifier and Type | Method and Description |
---|---|
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()
返回用于写入的锁。
|
public ReentrantReadWriteLock()
ReentrantReadWriteLock
与默认(非空)订购属性。
public ReentrantReadWriteLock(boolean fair)
ReentrantReadWriteLock
与给定的公平政策。
fair
-
true
如果此锁应使用合理的订购策略
public ReentrantReadWriteLock.WriteLock writeLock()
ReadWriteLock
复制
writeLock
在界面
ReadWriteLock
public ReentrantReadWriteLock.ReadLock readLock()
ReadWriteLock
复制
readLock
在界面
ReadWriteLock
public final boolean isFair()
true
。
true
如果这个锁的公平设置为true
protected Thread getOwner()
null
。
当这个方法被不是所有者的线程调用时,返回值反映了当前锁定状态的尽力近似。
例如,业主可能暂时null
即使有线程试图获取锁,但还没有这样做。
该方法旨在便于构建提供更广泛的锁定监控设施的子类。
null
如果不拥有
public int getReadLockCount()
public boolean isWriteLocked()
true
如果任何线程持有写锁定,
false
false
public boolean isWriteLockedByCurrentThread()
true
如果当前线程保持写锁定,
false
false
public int getWriteHoldCount()
public int getReadHoldCount()
protected Collection<Thread> getQueuedWriterThreads()
protected Collection<Thread> getQueuedReaderThreads()
public final boolean hasQueuedThreads()
true
返回不保证任何其他线程将获得锁。
该方法主要用于监视系统状态。
true
如果可能有其他线程等待获取锁
public final boolean hasQueuedThread(Thread thread)
true
返回不保证此线程将获得锁。
该方法主要用于监视系统状态。
thread
- 线程
true
如果给定的线程排队等待这个锁
NullPointerException
- 如果线程为空
public final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
public boolean hasWaiters(Condition condition)
true
返回不能保证将来的signal
将唤醒任何线程。
该方法主要用于监视系统状态。
condition
- 条件
true
如果有任何等待的线程
IllegalMonitorStateException
- 如果此锁不被保留
IllegalArgumentException
- 如果给定的条件不与此锁相关联
NullPointerException
- 如果条件为空
public int getWaitQueueLength(Condition condition)
condition
- 条件
IllegalMonitorStateException
- 如果此锁没有保持
IllegalArgumentException
- 如果给定的条件不与此锁相关联
NullPointerException
- 如果条件为空
protected Collection<Thread> getWaitingThreads(Condition condition)
condition
- 条件
IllegalMonitorStateException
- 如果此锁没有保持
IllegalArgumentException
- 如果给定的条件与此锁没有关联
NullPointerException
- 如果条件为空