Класс 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 |
Блокировка, возвращаемая методом 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 если для этой блокировки установлена честность 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)
- Параметры:
-
condition- условие - Возвращает:
- коллекцию потоков
- Выбрасывает:
-
IllegalMonitorStateException- если этот замок не удерживается -
IllegalArgumentException- если заданное условие не связано с этим замком -
NullPointerException- если условие равно null
toString
public String toString()
"Write locks =" , за которой следует количество повторно удерживаемых пишущих замков, и строку "Read locks =" , за которой следует количество удерживаемых читающих замков.- Overrides:
-
toStringв классеObject - Возвращает:
- строку, идентифицирующую данный замок, а также его состояние
© 1993, 2023, 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/21/docs/api/java.base/java/util/concurrent/locks/ReentrantReadWriteLock.html