java.lang.Object java.util.concurrent.locks.ReentrantReadWriteLock
public class ReentrantReadWriteLock
支持与 ReentrantLock
类似语义的 ReadWriteLock
实现。
此类具有以下属性:
此类不会将读取者优先或写入者优先强加给锁访问的排序。但是,它确实支持可选的公平 策略。
如果保持写入锁,或者有一个等待的 writer 线程,则试图获得公平读取锁(非重入地)的线程将会阻塞。直到当前最旧的等待 writer 线程已获得并释放了写入锁之后,该线程才会获得读取锁。当然,如果等待 writer 放弃其等待,而保留一个或更多 reader 线程为队列中带有写入锁自由的时间最长的 waiter,则将为那些 reader 分配读取锁。
试图获得公平写入锁的(非重入地)的线程将会阻塞,除非读取锁和写入锁都自由(这意味着没有等待线程)。(注意,非阻塞 ReentrantReadWriteLock.ReadLock.tryLock()
和 ReentrantReadWriteLock.WriteLock.tryLock()
方法不会遵守此公平设置,并将获得锁(如果可能),不考虑等待线程)。
此锁允许 reader 和 writer 按照 ReentrantLock
的样式重新获取读取锁或写入锁。在写入线程保持的所有写入锁都已经释放后,才允许重入 reader 使用它们。
此外,writer 可以获取读取锁,但反过来则不成立。在其他应用程序中,当在调用或回调那些在读取锁状态下执行读取操作的方法期间保持写入锁时,重入很有用。如果 reader 试图获取写入锁,那么将永远不会获得成功。
重入还允许从写入锁降级为读取锁,其实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的。
读取锁和写入锁都支持锁获取期间的中断。
Condition
支持 写入锁提供了一个 Condition
实现,对于写入锁来说,该实现的行为与 ReentrantLock.newCondition()
提供的 Condition
实现对 ReentrantLock
所做的行为相同。当然,此 Condition
只能用于写入锁。
读取锁不支持 Condition
,readLock().newCondition()
会抛出 UnsupportedOperationException
。
此类支持一些确定是保持锁还是争用锁的方法。这些方法设计用于监视系统状态,而不是同步控制。
此类行为的序列化方式与内置锁的相同:反序列化的锁处于解除锁状态,无论序列化该锁时其状态如何。
示例用法。下面的代码展示了如何利用重入来执行升级缓存后的锁降级(为简单起见,省略了异常处理):
class CachedData { Object data; volatile boolean cacheValid; 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(); // 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(); rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } }在使用某些种类的 Collection 时,可以使用 ReentrantReadWriteLock 来提高并发性。通常,在预期 collection 很大,读取者线程访问它的次数多于写入者线程,并且 entail 操作的开销高于同步开销时,这很值得一试。例如,以下是一个使用 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
。
嵌套类摘要 | |
---|---|
static class |
ReentrantReadWriteLock.ReadLock readLock() 方法返回的锁。 |
static class |
ReentrantReadWriteLock.WriteLock writeLock() 方法返回的锁。 |
构造方法摘要 | |
---|---|
ReentrantReadWriteLock() 使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock 。 |
|
ReentrantReadWriteLock(boolean fair) 使用给定的公平策略创建一个新的 ReentrantReadWriteLock 。 |
方法摘要 | |
---|---|
protected Thread |
getOwner() 返回当前拥有写入锁的线程,如果没有这样的线程,则返回 null 。 |
protected Collection<Thread> |
getQueuedReaderThreads() 返回一个 collection,它包含可能正在等待获取读取锁的线程。 |
protected Collection<Thread> |
getQueuedThreads() 返回一个 collection,它包含可能正在等待获取读取或写入锁的线程。 |
protected Collection<Thread> |
getQueuedWriterThreads() 返回一个 collection,它包含可能正在等待获取写入锁的线程。 |
int |
getQueueLength() 返回等待获取读取或写入锁的线程估计数目。 |
int |
getReadHoldCount() 查询当前线程在此锁上保持的重入读取锁数量。 |
int |
getReadLockCount() 查询为此锁保持的读取锁数量。 |
protected Collection<Thread> |
getWaitingThreads(Condition condition) 返回一个 collection,它包含可能正在等待与写入锁相关的给定条件的那些线程。 |
int |
getWaitQueueLength(Condition condition) 返回正等待与写入锁相关的给定条件的线程估计数目。 |
int |
getWriteHoldCount() 查询当前线程在此锁上保持的重入写入锁数量。 |
boolean |
hasQueuedThread(Thread thread) 查询是否给定线程正在等待获取读取或写入锁。 |
boolean |
hasQueuedThreads() 查询是否所有的线程正在等待获取读取或写入锁。 |
boolean |
hasWaiters(Condition condition) 查询是否有些线程正在等待与写入锁有关的给定条件。 |
boolean |
isFair() 如果此锁将公平性设置为 ture,则返回 true 。 |
boolean |
isWriteLocked() 查询是否某个线程保持了写入锁。 |
boolean |
isWriteLockedByCurrentThread() 查询当前线程是否保持了写入锁。 |
ReentrantReadWriteLock.ReadLock |
readLock() 返回用于读取操作的锁。 |
String |
toString() 返回标识此锁及其锁状态的字符串。 |
ReentrantReadWriteLock.WriteLock |
writeLock() 返回用于写入操作的锁。 |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
构造方法详细信息 |
---|
public ReentrantReadWriteLock()
ReentrantReadWriteLock
。
public ReentrantReadWriteLock(boolean fair)
ReentrantReadWriteLock
。
fair
- 如果此锁应该使用公平排序策略,则该参数的值为
true
方法详细信息 |
---|
public ReentrantReadWriteLock.WriteLock writeLock()
ReadWriteLock
复制的描述
ReadWriteLock
中的
writeLock
public ReentrantReadWriteLock.ReadLock readLock()
ReadWriteLock
复制的描述
ReadWriteLock
中的
readLock
public final boolean isFair()
true
。
true
protected Thread getOwner()
null
。当通过不是所有者的线程调用此方法时,返回值反映当前锁状态的最接近近似值。例如,即使存在试图获得锁的线程,但是在它还没有获得前,所有者可能暂时为
null
。设计此方法是为了便于构造提供更多扩展的锁监视设施的子类。
null
public int getReadLockCount()
public boolean isWriteLocked()
true
;否则返回
false
public boolean isWriteLockedByCurrentThread()
true
;否则返回
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
- 如果线程为 null
public final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
public boolean hasWaiters(Condition condition)
true
并不保证将来某个
signal
将唤醒任何线程。此方法主要用于监视系统状态。
condition
- 条件
true
IllegalMonitorStateException
- 如果没有保持此锁
IllegalArgumentException
- 如果给定的条件与此锁无关
NullPointerException
- 如果条件为 null
public int getWaitQueueLength(Condition condition)
condition
- 条件
IllegalMonitorStateException
- 如果没有保持此锁
IllegalArgumentException
- 如果给定的条件与此锁无关
NullPointerException
- 如果条件为 null
protected Collection<Thread> getWaitingThreads(Condition condition)
condition
- 条件
IllegalMonitorStateException
- 如果没有保持此锁
IllegalArgumentException
- 如果给定 condition 与此锁无关
NullPointerException
- 如果条件为 null
public String toString()