Module  java.base

Class ReentrantReadWriteLock

  • All Implemented Interfaces:
    SerializableReadWriteLock


    public class ReentrantReadWriteLock
    extends Object
    implements ReadWriteLock, Serializable
    支持ReadWriteLock类似语义ReentrantLock的实现

    此类具有以下属性:

    • 收购令

      此类不会强制使用读取器或写入器优先顺序进行锁定访问。 但是,它确实支持可选的公平政策。

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

      尝试获取公平读锁(不可重入)的线程将阻塞,如果写锁定或有等待的写入程序线程。 直到最旧的当前正在等待的写入程序线程获取并释放写入锁之后,该线程才会获取读锁定。 当然,如果一个等待的作家放弃了等待,留下一个或多个阅读器线程作为队列中最长的服务器,其中写锁定空闲,那么这些读取器将被分配读取锁定。

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

    • 重入

      这个锁允许读者和作者以ReentrantLock的风格重新获取读写锁。 在写入线程所持有的所有写入锁已经被释放之前,不允许非重入读取器。

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

    • 锁定降级

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

    • 中断锁获取

      读取锁定和写入锁定在锁定采集期间都支持中断。

    • Condition支持

      写入锁提供了一个Condition实现,其行为以同样的方式,相对于写入锁定,为Condition提供实现ReentrantLock.newCondition()确实为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如果这个锁的公平设置为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 - 如果条件为空
      • toString

        public String toString​()
        返回一个标识此锁的字符串以及其锁定状态。 括号中的状态包括字符串"Write locks ="其后是可重入的写入锁的数量,而字符串"Read locks ="之后是持有的读锁定数。
        重写:
        toStringObject
        结果
        标识此锁的字符串以及其锁定状态