Класс ReentrantReadWriteLock
- java.lang.Object
-
- java.util.concurrent.locks.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;
volatile 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<String, Data>();
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 String[] allKeys() {
r.lock();
try { return m.keySet().toArray(); }
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 Блокировка, возвращаемая методом |
static class |
ReentrantReadWriteLock.WriteLock Блокировка, возвращаемая методом |
Конструкторы
| Конструктор и описание |
|---|
ReentrantReadWriteLock() Создает новую |
ReentrantReadWriteLock(boolean fair) Создает новую |
Методы
| Модификатор и тип | Метод и описание |
|---|---|
protected Thread |
getOwner() Возвращает поток, который в настоящее время владеет блокировкой записи, или |
protected Collection<Thread> |
getQueuedReaderThreads() Возвращает коллекцию, содержащую потоки, которые могут ожидать приобретения блокировки для чтения. |
protected Collection<Thread> |
getQueuedThreads() Возвращает коллекцию, содержащую потоки, которые могут ожидать приобретения блокировки для чтения или записи. |
protected Collection<Thread> |
getQueuedWriterThreads() Возвращает коллекцию, содержащую потоки, которые могут ожидать приобретения блокировки для записи. |
int |
getQueueLength() Возвращает приблизительное количество потоков, ожидающих приобретения блокировки для чтения или записи. |
int |
getReadHoldCount() Запрашивает количество рекурсивных удержаний блокировки для чтения текущим потоком. |
int |
getReadLockCount() Запрашивает количество удерживаемых блокировок для чтения. |
protected Collection<Thread> |
getWaitingThreads(Condition condition) Возвращает коллекцию, содержащую потоки, которые могут ожидать условия, связанного с блокировкой для записи. |
int |
getWaitQueueLength(Condition condition) Возвращает приблизительное количество потоков, ожидающих условия, связанного с блокировкой для записи. |
int |
getWriteHoldCount() Запрашивает количество рекурсивных удержаний блокировки для записи текущим потоком. |
boolean |
hasQueuedThread(Thread thread) Запрашивает, ожидает ли указанный поток приобретения блокировки для чтения или записи. |
boolean |
hasQueuedThreads() Запрашивает, ожидают ли какие-либо потоки приобретения блокировки для чтения или записи. |
boolean |
hasWaiters(Condition condition) Запрашивает, ожидают ли какие-либо потоки условия, связанного с блокировкой для записи. |
boolean |
isFair() Возвращает |
boolean |
isWriteLocked() Запрашивает, удерживается ли блокировка для записи каким-либо потоком. |
boolean |
isWriteLockedByCurrentThread() Запрашивает, удерживается ли блокировка для записи текущим потоком. |
ReentrantReadWriteLock.ReadLock |
readLock() Возвращает блокировку, используемую для чтения. |
String |
toString() Возвращает строку, идентифицирующую эту блокировку, а также ее состояние. |
ReentrantReadWriteLock.WriteLock |
writeLock() Возвращает блокировку, используемую для записи. |
Методы, унаследованные от класса java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, 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, 2020, 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.