java.util.concurrent.locks
类 ReentrantReadWriteLock

java.lang.Object
  继承者 java.util.concurrent.locks.ReentrantReadWriteLock
所有已实现的接口:
Serializable, ReadWriteLock

public class ReentrantReadWriteLock
   
   
   
extends Object
implements ReadWriteLock, Serializable

支持与 ReentrantLock 类似语义的 ReadWriteLock 实现。

此类具有以下属性:

  • 获取顺序

    此类不会将读取者优先或写入者优先强加给锁访问的排序。但是,它确实支持可选的公平 策略。

    非公平模式(默认)
    当非公平地(默认)构造时,未指定进入读写锁的顺序,受到 reentrancy 约束的限制。连续竞争的非公平锁可能无限期地推迟一个或多个 reader 或 writer 线程,但吞吐量通常要高于公平锁。

    公平模式
    当公平地构造线程时,线程利用一个近似到达顺序的策略来争夺进入。当释放当前保持的锁时,可以为等待时间最长的单个 writer 线程分配写入锁,如果有一组等待时间大于所有正在等待的 writer 线程 的 reader 线程,将为该组分配写入锁。

    如果保持写入锁,或者有一个等待的 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 只能用于写入锁。

    读取锁不支持 ConditionreadLock().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

从以下版本开始:
1.5
另请参见:
序列化表格

嵌套类摘要
static classReentrantReadWriteLock.ReadLock
          readLock() 方法返回的锁。
static classReentrantReadWriteLock.WriteLock
          writeLock() 方法返回的锁。
 
构造方法摘要
ReentrantReadWriteLock()
          使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock
ReentrantReadWriteLock(boolean fair)
          使用给定的公平策略创建一个新的 ReentrantReadWriteLock
 
方法摘要
protected  ThreadgetOwner()
          返回当前拥有写入锁的线程,如果没有这样的线程,则返回 null
protected  Collection<Thread>getQueuedReaderThreads()
          返回一个 collection,它包含可能正在等待获取读取锁的线程。
protected  Collection<Thread>getQueuedThreads()
          返回一个 collection,它包含可能正在等待获取读取或写入锁的线程。
protected  Collection<Thread>getQueuedWriterThreads()
          返回一个 collection,它包含可能正在等待获取写入锁的线程。
 intgetQueueLength()
          返回等待获取读取或写入锁的线程估计数目。
 intgetReadHoldCount()
          查询当前线程在此锁上保持的重入读取锁数量。
 intgetReadLockCount()
          查询为此锁保持的读取锁数量。
protected  Collection<Thread>getWaitingThreads(Condition condition)
          返回一个 collection,它包含可能正在等待与写入锁相关的给定条件的那些线程。
 intgetWaitQueueLength(Condition condition)
          返回正等待与写入锁相关的给定条件的线程估计数目。
 intgetWriteHoldCount()
          查询当前线程在此锁上保持的重入写入锁数量。
 booleanhasQueuedThread(Thread thread)
          查询是否给定线程正在等待获取读取或写入锁。
 booleanhasQueuedThreads()
          查询是否所有的线程正在等待获取读取或写入锁。
 booleanhasWaiters(Condition condition)
          查询是否有些线程正在等待与写入锁有关的给定条件。
 booleanisFair()
          如果此锁将公平性设置为 ture,则返回 true
 booleanisWriteLocked()
          查询是否某个线程保持了写入锁。
 booleanisWriteLockedByCurrentThread()
          查询当前线程是否保持了写入锁。
 ReentrantReadWriteLock.ReadLockreadLock()
          返回用于读取操作的锁。
 StringtoString()
          返回标识此锁及其锁状态的字符串。
 ReentrantReadWriteLock.WriteLockwriteLock()
          返回用于写入操作的锁。
 
从类 java.lang.Object 继承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

构造方法详细信息

ReentrantReadWriteLock

public ReentrantReadWriteLock()
使用默认(非公平)的排序属性创建一个新的 ReentrantReadWriteLock


ReentrantReadWriteLock

public ReentrantReadWriteLock(boolean fair)
使用给定的公平策略创建一个新的 ReentrantReadWriteLock

参数:
fair - 如果此锁应该使用公平排序策略,则该参数的值为 true
方法详细信息

writeLock

public ReentrantReadWriteLock.WriteLock writeLock()
从接口 ReadWriteLock 复制的描述
返回用于写入操作的锁。

指定者:
接口 ReadWriteLock 中的 writeLock
返回:
用于写入操作的锁。

readLock

public ReentrantReadWriteLock.ReadLock readLock()
从接口 ReadWriteLock 复制的描述
返回用于读取操作的锁。

指定者:
接口 ReadWriteLock 中的 readLock
返回:
用于读取操作的锁。

isFair

public final boolean isFair()
如果此锁将公平性设置为 ture,则返回 true

返回:
如果此锁将公平性设置为 ture,则返回 true

getOwner

protected Thread getOwner()
返回当前拥有写入锁的线程,如果没有这样的线程,则返回 null。当通过不是所有者的线程调用此方法时,返回值反映当前锁状态的最接近近似值。例如,即使存在试图获得锁的线程,但是在它还没有获得前,所有者可能暂时为 null。设计此方法是为了便于构造提供更多扩展的锁监视设施的子类。

返回:
所有者;如果没有所有者,则返回 null

getReadLockCount

public int getReadLockCount()
查询为此锁保持的读取锁数量。此方法设计用于监视系统状态,而不是同步控制。

返回:
所保持的读取锁数量。