Класс 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(); }
}
} Примечания к реализации
Эта блокировка поддерживает максимальное количество 65535 рекурсивных блокировок записи и 65535 блокировок чтения. Попытки превысить эти пределы приводят к исключению 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.- Возвращает:
-
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)
- Parameters:
-
condition- условие - Returns:
- коллекция потоков
- Throws:
-
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://download.java.net/java/early_access/jdk24/docs/api/java.base/java/util/concurrent/locks/ReentrantReadWriteLock.html