Класс ReentrantReadWriteLock
- Все реализуемые интерфейсы:
Serializable, ReadWriteLock
public class ReentrantReadWriteLock extends Object implements ReadWriteLock, Serializable
ReadWriteLock, поддерживающая семантику, аналогичную ReentrantLock. Этот класс обладает следующими свойствами:
-
Порядок получения
Этот класс не устанавливает предпочтительный порядок доступа к блокировке для читателей или писателей. Однако он поддерживает необязательную политику справедливости.
- Несправедливый режим (по умолчанию)
- При создании в несправедливом режиме (по умолчанию) порядок получения блокировок чтения и записи не определен и зависит от ограничений реентерабельности. Несправедливая блокировка, за которую непрерывно конкурируют потоки, может неопределенно долго откладывать выполнение одного или нескольких потоков-читателей или потоков-писателей, но обычно обеспечивает более высокую пропускную способность, чем справедливая блокировка.
- Справедливый режим
- При создании в справедливом режиме потоки конкурируют за получение блокировки в приблизительном порядке поступления. Когда текущая блокировка освобождается, блокировка записи назначается либо потоку-писателю, который дольше всех ожидает, либо группе потоков-читателей, если она ожидает дольше всех потоков-писателей.
Поток, пытающийся получить справедливую блокировку чтения (не реентерабельно), будет заблокирован, если удерживается блокировка записи или ожидает поток-писатель. Поток не получит блокировку чтения, пока самый давно ожидающий поток-писатель не получит и не освободит блокировку записи. Разумеется, если ожидающий писатель прекратит ожидание и в очереди останутся один или несколько потоков-читателей, ожидающих дольше остальных, а блокировка записи будет свободна, этим читателям будет назначена блокировка чтения.
Поток, пытающийся получить справедливую блокировку записи (не реентерабельно), будет заблокирован, пока обе блокировки — чтения и записи — не освободятся (это означает, что ожидающих потоков нет). (Обратите внимание: неблокирующие методы
ReentrantReadWriteLock.ReadLock.tryLock()иReentrantReadWriteLock.WriteLock.tryLock()не учитывают эту настройку справедливости и немедленно получают блокировку, если это возможно, независимо от ожидающих потоков.)
-
Реентерабельность
Эта блокировка позволяет как читателям, так и писателям повторно получать блокировки чтения или записи по принципу
ReentrantLock. Потоки-читатели, не являющиеся реентерабельными, не допускаются, пока пишущий поток не освободит все удерживаемые им блокировки записи.Кроме того, писатель может получить блокировку чтения, но не наоборот. Среди прочего, реентерабельность может быть полезна, когда блокировки записи удерживаются во время вызовов или обратных вызовов методов, выполняющих чтение под блокировками чтения. Если читатель попытается получить блокировку записи, ему это никогда не удастся.
Примечание. Если вы не полагаетесь на реентерабельность,
StampedLockможет обеспечить более высокую производительность, например:ReadWriteLock lock = new StampedLock().asReadWriteLock(). -
Понижение блокировки
Реентерабельность также позволяет понизить блокировку записи до блокировки чтения: для этого нужно получить блокировку записи, затем блокировку чтения и после этого освободить блокировку записи. Однако повысить блокировку чтения до блокировки записи невозможно.
-
Прерывание при получении блокировки
Блокировки чтения и записи поддерживают прерывание во время получения блокировки.
-
Поддержка
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() |
Возвращает блокировку, используемую для записи. |
Методы, объявленные в классе Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait | Модификатор и тип | Метод | Описание |
|---|---|---|
protected Object |
clone() |
Создает и возвращает копию этого объекта. |
boolean |
equals |
Показывает, равен ли этот объект другому объекту. |
protected void |
finalize() |
Устарело, будет удалено: этот элемент API может быть удален в будущей версии. Финализация объявлена устаревшей и будет удалена в одном из следующих выпусков. |
final Class |
getClass() |
Возвращает класс времени выполнения этого Object. |
int |
hashCode() |
Возвращает хеш-код этого объекта. |
final void |
notify() |
Пробуждает один поток, ожидающий на мониторе этого объекта. |
final void |
notifyAll() |
Пробуждает все потоки, ожидающие на мониторе этого объекта. |
final void |
wait() |
Заставляет текущий поток ожидать пробуждения, обычно в результате уведомления или прерывания. |
final void |
wait |
Заставляет текущий поток ожидать пробуждения, обычно в результате уведомления или прерывания, либо до истечения заданного промежутка реального времени. |
final void |
wait |
Заставляет текущий поток ожидать пробуждения, обычно в результате уведомления или прерывания, либо до истечения заданного промежутка реального времени. |
Подробное описание конструкторов
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.