Класс ReentrantReadWriteLock

Все реализованные интерфейсы:
Serializable, ReadWriteLock
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;
   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();
     }
   }
 }
Блокировки ReentrantReadWriteLock могут быть использованы для повышения конкуретности в некоторых применениях некоторых видов коллекций. Это обычно целесообразно только в том случае, если коллекции ожидаются быть большими, к ним обращаются больше потоков чтения, чем записи, и предполагаемые операции имеют издержки, превышающие затраты на синхронизацию. Например, вот класс, использующий 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
См. также:
Сериализованная форма

Вложенные классы

Модификатор и тип Класс Описание
static class  ReentrantReadWriteLock.ReadLock

Блокировка, возвращаемая методом ReadWriteLock.readLock().

static class  ReentrantReadWriteLock.WriteLock

Блокировка, возвращаемая методом ReadWriteLock.writeLock().

Конструкторы

Конструктор Описание
ReentrantReadWriteLock()

Создает новую ReentrantReadWriteLock с параметрами упорядочения по умолчанию (нечестность).

ReentrantReadWriteLock​(boolean fair)

Создает новую ReentrantReadWriteLock с заданной политикой честности.

Методы

Модификатор и тип Метод Описание
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 если для этой блокировки установлен режим честности.

boolean isWriteLocked()

Запрашивает, удерживается ли блокировка записи каким-либо потоком.

boolean isWriteLockedByCurrentThread()

Запрашивает, удерживается ли блокировка записи текущим потоком.

String toString()

Возвращает строку, идентифицирующую эту блокировку, а также ее состояние блокировки.

Методы, объявленные в классе java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Методы, объявленные в интерфейсе java.util.concurrent.locks.ReadWriteLock

readLock, writeLock

Конструкторы

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 - если поток равен null

getQueueLength

public final int getQueueLength()

Возвращает оценку количества потоков, ожидающих получения блокировки чтения или записи. Значение является лишь оценкой, так как количество потоков может динамически изменяться во время перебора внутренних структур данных. Этот метод предназначен для использования в мониторинге состояния системы, а не для управления синхронизацией.

Возвращает:
приблизительное количество потоков, ожидающих этой блокировки

getQueuedThreads

protected Collection<Thread> getQueuedThreads()

Возвращает коллекцию, содержащую потоки, которые могут ожидать получения блокировки чтения или записи. Поскольку фактический набор потоков может динамически изменяться во время построения этого результата, возвращаемая коллекция является лишь приблизительной оценкой. Элементы возвращаемой коллекции расположены в произвольном порядке. Этот метод предназначен для облегчения создания подклассов, которые предоставляют более подробные средства мониторинга.

Возвращает:
коллекцию потоков

hasWaiters

public boolean hasWaiters(Condition condition)

Запрашивает, ожидают ли какие-либо потоки на заданном условии, связанном с блокировкой записи. Обратите внимание, что из-за таймаутов и прерываний, которые могут произойти в любое время, возвращение true не гарантирует, что в будущем signal разбудит какие-либо потоки. Этот метод предназначен в основном для использования в мониторинге состояния системы.

Параметры:
condition - условие
Возвращает:
true если существуют ожидающие потоки
Исключение:
IllegalMonitorStateException - если эта блокировка не удерживается
IllegalArgumentException - если заданное условие не связано с этой блокировкой
NullPointerException - если условие равно null

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 =" , за которой следует число удерживаемых блокировок чтения.

Переопределяет:
toString в классе Object
Возвращает:
строку, идентифицирующую эту блокировку, а также её состояние блокировки

© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/locks/ReentrantReadWriteLock.html

Spec-Zone .ru
спецификации, руководства, описания, API