Класс 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();
}
}
} Блокировки ReentrantReadWrite могут использоваться для повышения конкурении в некоторых случаях использования некоторых типов коллекций. Это обычно стоит того только в том случае, если коллекции ожидаются большими, доступ к ним получают больше потоков-читателей, чем потоков-писателей, и операции требуют вычислений, которые перевешивают расходы на синхронизацию. Например, здесь представлен класс, использующий 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 в методах блокировки.
- Since:
- 1.5
- См. также:
Краткое описание вложенных классов
| Модификатор и тип | Класс | Описание |
|---|---|---|
static class |
ReentrantReadWriteLock.ReadLock |
Блокировка, возвращаемая методом readLock(). |
static class |
ReentrantReadWriteLock.WriteLock |
Блокировка, возвращаемая методом writeLock(). |
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
ReentrantReadWriteLock() |
Создаёт новую ReentrantReadWriteLock с параметрами по умолчанию (несправедливый) порядок. |
ReentrantReadWriteLock |
Создаёт новую ReentrantReadWriteLock с заданной политикой справедливости. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
protected Thread |
getOwner() |
Возвращает поток, который в данный момент владеет блокировкой записи, или null если нет владельца. |
protected Collection<Thread> |
getQueuedReaderThreads() |
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения блокировки чтения. |
protected Collection<Thread> |
getQueuedThreads() |
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения блокировки чтения или записи. |
protected Collection<Thread> |
getQueuedWriterThreads() |
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения блокировки записи. |
final int |
getQueueLength() |
Возвращает приблизительное количество потоков, ожидающих получения блокировки чтения или записи. |
int |
getReadHoldCount() |
Запрашивает количество рекурсивных блокировок чтения для текущего потока на этой блокировке. |
int |
getReadLockCount() |
Запрашивает количество блокировок чтения, удерживаемых для этой блокировки. |
protected Collection<Thread> |
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 =" , за которой следует количество удерживаемых читающих замков.- Overrides:
-
toStringв классеObject - Возвращает:
- строку, идентифицирующую этот замок, а также его состояние
© 1993, 2021, 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/17/docs/api/java.base/java/util/concurrent/locks/ReentrantReadWriteLock.html