模块  java.base

Class ReentrantReadWriteLock

  • 实现的所有接口
    SerializableReadWriteLock

    public class ReentrantReadWriteLockextends Objectimplements ReadWriteLock, Serializable
    的实现ReadWriteLock支持类似的语义ReentrantLock

    该类具有以下属性:

    • 收购订单

      此类不会强制执行锁定访问的读取器或编写器首选项顺序。 但是,它确实支持可选的公平政策。

      非公平模式(默认)
      当构造为非公平(默认)时,读取和写入锁定的输入顺序是未指定的,受重入约束的限制。 持续争用的非公平锁定可能无限期地推迟一个或多个读取器或写入器线程,但通常具有比公平锁定更高的吞吐量。
      公平模式
      当构造为公平时,线程使用近似到达顺序策略争用进入。 当释放当前保持的锁定时,将为最长等待的单个写入器线程分配写入锁定,或者如果有一组读取器线程等待的时间长于所有等待的写入器线程,则将为该组分配读取锁定。

      尝试获取公平读锁定(非重复)的线程将阻止是否保持写锁定,或者存在等待写入器线程。 在最旧的当前等待的写入器线程获取并释放写锁定之前,线程将不会获取读锁定。 当然,如果等待的写入者放弃其等待,将一个或多个读取器线程作为队列中最长的服务器并且写锁定空闲,那么将为这些读取器分配读锁定。

      尝试获取公平写锁定(非重复)的线程将阻塞,除非读取锁定和写入锁定都是空闲的(这意味着没有等待的线程)。 (请注意,非阻塞ReentrantReadWriteLock.ReadLock.tryLock()ReentrantReadWriteLock.WriteLock.tryLock()方法不遵循此公平设置,并且如果可能,将立即获取锁定,无论等待线程如何。)

    • 重入

      此锁允许读取器和写入器以ReentrantLock的样式重新获取读或写锁。 在写入线程持有的所有写锁定都被释放之前,不允许使用非重入读取器。

      此外,编写器可以获取读锁定,但反之亦然。 在其他应用程序中,在调用期间保持写入锁定或在对读取锁定执行读取的方法的回调时,重入可能很有用。 如果读者试图获取写锁定,它将永远不会成功。

    • 锁定降级

      Reentrancy还允许通过获取写锁定,然后读取锁定然后释放写入锁定,从写入锁定降级到读取锁定。 然而,从读锁定写锁定升级是不可能的。

    • 锁定获取中断

      读取锁定和写入锁定都支持锁定获取期间的中断。

    • Condition支持

      写锁定提供Condition实现,相对于写锁定,其行为方式相同,因为ReentrantLock.newCondition()提供的Condition实现针对ReentrantLock 当然,这个Condition只能与写锁一起使用。

      读锁定不支持ConditionreadLock().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(); } } } 
    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
    另请参见:
    Serialized Form
    • 构造方法详细信息

      • ReentrantReadWriteLock

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

        public ReentrantReadWriteLock​(boolean fair)
        使用给定的公平政策创建新的 ReentrantReadWriteLock
        参数
        fair - true如果此锁应使用公平订购政策
    • 方法详细信息

      • isFair

        public final boolean isFair()
        如果此锁定的公平性设置为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 - 如果线程为null
      • 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 - 如果条件为null
      • getWaitingThreads

        protected Collection<Thread> getWaitingThreads​(Condition condition)
        返回一个集合,其中包含可能正在等待与写入锁定关联的给定条件的那些线程。 因为实际的线程集可能在构造此结果时动态更改,所以返回的集合仅是尽力而为的估计。 返回集合的元素没有特定的顺序。 该方法旨在便于构建提供更广泛的状态监测设施的子类。
        参数
        condition - 条件
        结果
        线程集合
        异常
        IllegalMonitorStateException - 如果未锁定此锁定
        IllegalArgumentException - 如果给定条件与此锁定无关
        NullPointerException - 如果条件为null
      • toString

        public String toString()
        返回标识此锁的字符串及其锁定状态。 括号中的状态包括字符串"Write locks ="后跟重新保存的写锁定数,以及字符串"Read locks ="后跟保持的读锁定数。
        重写:
        toStringObject
        结果
        标识此锁的字符串及其锁定状态