Класс 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();
// Code between the lock() above, and the unlock() below must not throw
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
}
}
// Make sure that code that could throw is executed inside the try block
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(); }
}
} Примечания по реализации
Эта блокировка поддерживает максимум Integer.MAX_VALUE рекурсивных блокировок записи и Integer.MAX_VALUE блокировок чтения. При попытке превысить эти пределы методы блокировки выбрасывают Error.
- С версии:
- 1.5
- См. также:
Краткое описание вложенных классов
| Модификатор и тип | Класс | Описание |
|---|---|---|
static class |
ReentrantReadWriteLock.ReadLock |
Блокировка, возвращаемая методом readLock(). |
static class |
ReentrantReadWriteLock.WriteLock |
Блокировка, возвращаемая методом writeLock(). |
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
ReentrantReadWriteLock() |
Создает новый ReentrantReadWriteLock со свойствами порядка по умолчанию (несправедливый режим). |
ReentrantReadWriteLock |
Создает новый ReentrantReadWriteLock с заданной политикой справедливости. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
protected Thread |
getOwner() |
Возвращает поток, который в данный момент владеет блокировкой записи, или null, если блокировка никем не удерживается. |
protected Collection |
getQueuedReaderThreads() |
Возвращает коллекцию, содержащую потоки, которые, возможно, ожидают получения блокировки чтения. |
protected Collection |
getQueuedThreads() |
Возвращает коллекцию, содержащую потоки, которые, возможно, ожидают получения блокировки чтения или записи. |
protected Collection |
getQueuedWriterThreads() |
Возвращает коллекцию, содержащую потоки, которые, возможно, ожидают получения блокировки записи. |
final int |
getQueueLength() |
Возвращает оценочное количество потоков, ожидающих получения блокировки чтения или записи. |
int |
getReadHoldCount() |
Запрашивает количество реентерабельных блокировок чтения этой блокировки, удерживаемых текущим потоком. |
int |
getReadLockCount() |
Запрашивает количество блокировок чтения, удерживаемых для этой блокировки. |
protected Collection |
getWaitingThreads |
Возвращает коллекцию, содержащую потоки, которые, возможно, ожидают указанного условия, связанного с блокировкой записи. |
int |
getWaitQueueLength |
Возвращает оценочное количество потоков, ожидающих указанного условия, связанного с блокировкой записи. |
int |
getWriteHoldCount() |
Запрашивает количество реентерабельных блокировок записи этой блокировки, удерживаемых текущим потоком. |
final boolean |
hasQueuedThread |
Запрашивает, ожидает ли указанный поток получения блокировки чтения или записи. |
final boolean |
hasQueuedThreads() |
Запрашивает, ожидают ли какие-либо потоки получения блокировки чтения или записи. |
boolean |
hasWaiters |
Запрашивает, ожидают ли какие-либо потоки указанного условия, связанного с блокировкой записи. |
final boolean |
isFair() |
Возвращает true, если для этой блокировки задан справедливый режим. |
boolean |
isWriteLocked() |
Запрашивает, удерживается ли блокировка записи каким-либо потоком. |
boolean |
isWriteLockedByCurrentThread() |
Запрашивает, удерживается ли блокировка записи текущим потоком. |
ReentrantReadWriteLock.ReadLock |
readLock() |
Возвращает блокировку, используемую для чтения. |
String |
toString() |
Возвращает строку, идентифицирующую эту блокировку, а также ее состояние. |
ReentrantReadWriteLock.WriteLock |
writeLock() |
Возвращает блокировку, используемую для записи. |
Подробное описание конструкторов
ReentrantReadWriteLock
public ReentrantReadWriteLock()
ReentrantReadWriteLock со свойствами порядка по умолчанию (несправедливый режим).ReentrantReadWriteLock
public ReentrantReadWriteLock(boolean fair)
ReentrantReadWriteLock с заданной политикой справедливости.- Параметры:
-
fair—true, если для этой блокировки следует использовать справедливую политику порядка
Подробное описание методов
writeLock
public ReentrantReadWriteLock.WriteLock writeLock()
ReadWriteLock- Определено в:
-
writeLockв интерфейсеReadWriteLock - Возвращает:
- блокировку, используемую для записи
readLock
public ReentrantReadWriteLock.ReadLock readLock()
ReadWriteLock- Определено в:
-
readLockв интерфейсеReadWriteLock - Возвращает:
- блокировку, используемую для чтения
isFair
public final boolean isFair()
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 =", за которой следует количество удерживаемых блокировок чтения.
© 1993, 2025, 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/25/docs/api/java.base/java/util/concurrent/locks/ReentrantReadWriteLock.html