Класс ReentrantLock
- java.lang.Object
-
- java.util.concurrent.locks.ReentrantLock
- Все реализованные интерфейсы:
- Serializable, Lock
public class ReentrantLock extends Object implements Lock, Serializable
Рекурсивный взаимный исключающий Lock с тем же базовым поведением и семантикой, что и неявный мониторный замок, доступ к которому осуществляется с помощью synchronized методов и инструкций, но с расширенными возможностями.
ReentrantLock принадлежит потоку, последнему успешно заблокировавшему, но ещё не разблокировавшему его. Поток, вызывающий lock , вернётся, успешно получив замок, когда замок не принадлежит другому потоку. Метод вернётся сразу же, если текущий поток уже владеет замком. Это можно проверить с помощью методов isHeldByCurrentThread() и getHoldCount().
Конструктор этого класса принимает необязательный параметр справедливости. Когда он установлен true, при конкуренции замки отдают предпочтение предоставлению доступа потоку, который дольше всего ожидает. В противном случае этот замок не гарантирует какой-либо определённый порядок доступа. Программы, использующие справедливые замки, доступ к которым осуществляется многими потоками, могут демонстрировать более низкую общую производительность (то есть, медленнее; часто намного медленнее), чем те, которые используют настройки по умолчанию, но имеют меньшие колебания во времени получения замков и гарантируют отсутствие голодания. Однако следует отметить, что справедливость замков не гарантирует справедливости планирования потоков. Таким образом, один из многих потоков, использующих справедливый замок, может получить его несколько раз подряд, в то время как другие активные потоки не прогрессируют и в настоящее время не владеют замком. Также следует отметить, что асинхронный метод tryLock() не учитывает настройку справедливости. Он будет успешным, если замок доступен, даже если другие потоки ожидают.
Рекомендуется всегда сразу же после вызова lock использовать try блок, чаще всего в конструкции типа «до/после»:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
} Помимо реализации интерфейса Lock, этот класс определяет ряд public и protected методов для проверки состояния замка. Некоторые из этих методов полезны только для инструментирования и мониторинга.
Сериализация этого класса ведёт себя так же, как встроенные замки: десериализованный замок находится в разблокированном состоянии, независимо от его состояния при сериализации.
Этот замок поддерживает максимальное количество 2147483647 рекурсивных блокировок одним и тем же потоком. Попытки превысить этот лимит приводят к Error выбрасываемым из методов блокировки.
- Since:
- 1.5
- См. также:
- Сериализованная форма
Конструкторы
| Конструктор и описание |
|---|
ReentrantLock() Создаёт экземпляр |
ReentrantLock(boolean fair) Создаёт экземпляр |
Методы
| Модификатор и тип | Метод и описание |
|---|---|
int |
getHoldCount() Запрашивает количество удержаний этого замка текущим потоком. |
protected Thread |
getOwner() Возвращает поток, который в настоящее время владеет этим замком, или |
protected Collection<Thread> |
getQueuedThreads() Возвращает коллекцию, содержащую потоки, которые могут ожидать получения этого замка. |
int |
getQueueLength() Возвращает оценку количества потоков, ожидающих получения этого замка. |
protected Collection<Thread> |
getWaitingThreads(Condition condition) Возвращает коллекцию, содержащую те потоки, которые могут ожидать условного значения, связанного с этим замком. |
int |
getWaitQueueLength(Condition condition) Возвращает оценку количества потоков, ожидающих условного значения, связанного с этим замком. |
boolean |
hasQueuedThread(Thread thread) Запрашивает, ожидает ли заданный поток получения этого замка. |
boolean |
hasQueuedThreads() Запрашивает, ожидают ли какие-либо потоки получения этого замка. |
boolean |
hasWaiters(Condition condition) Запрашивает, ожидают ли какие-либо потоки условного значения, связанного с этим замком. |
boolean |
isFair() Возвращает |
boolean |
isHeldByCurrentThread() Запрашивает, держит ли текущий поток этот замок. |
boolean |
isLocked() Запрашивает, держит ли какой-либо поток этот замок. |
void |
lock() Получает замок. |
void |
lockInterruptibly() Получает замок, если текущий поток не был прерван. |
Condition |
newCondition() Возвращает экземпляр |
String |
toString() Возвращает строку, идентифицирующую этот замок, а также его состояние. |
boolean |
tryLock() Получает замок только в том случае, если он не удерживается другим потоком в момент вызова. |
boolean |
tryLock(long timeout,
TimeUnit unit) Получает замок, если он не удерживается другим потоком в течение заданного времени ожидания, и текущий поток не был прерван. |
void |
unlock() Попытка разблокировать этот замок. |
Методы, унаследованные от класса java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait Конструкторы
ReentrantLock
public ReentrantLock()
Создаёт экземпляр ReentrantLock. Это эквивалентно использованию ReentrantLock(false).
ReentrantLock
public ReentrantLock(boolean fair)
Создаёт экземпляр ReentrantLock с заданной политикой честности.
- Параметры:
-
fair-trueесли для этого мьютекса должна использоваться политика честного порядка очереди
Методы
lock
public void lock()
Приобретает мьютекс.
Приобретает мьютекс, если он не удерживается другой нитью, и возвращается немедленно, устанавливая счётчик удержания мьютекса в единицу.
Если текущая нить уже держит мьютекс, то счётчик удержания увеличивается на единицу, и метод возвращается немедленно.
Если мьютекс удерживается другой нитью, то текущая нить отключается для планирования потоков и находится в ожидании, пока мьютекс не будет приобретён, после чего счётчик удержания устанавливается в единицу.
lockInterruptibly
public void lockInterruptibly()
throws InterruptedException Приобретает мьютекс, если текущая нить не прервана.
Приобретает мьютекс, если он не удерживается другой нитью, и возвращается немедленно, устанавливая счётчик удержания мьютекса в единицу.
Если текущая нить уже держит этот мьютекс, то счётчик удержания увеличивается на единицу, и метод возвращается немедленно.
Если мьютекс удерживается другой нитью, то текущая нить отключается для планирования потоков и находится в ожидании, пока не произойдёт одно из двух:
- Мьютекс приобретается текущей нитью; или
- Другая нить прерывает текущую нить.
Если мьютекс приобретается текущей нитью, то счётчик удержания устанавливается в единицу.
Если текущая нить:
- имеет свой флаг прерывания установленным в начале выполнения этого метода; или
- была прервана во время приобретения мьютекса,
InterruptedException, и флаг прерывания текущей нити сбрасывается. В этой реализации, поскольку этот метод является явной точкой прерывания, приоритет отдаётся обработке прерывания перед обычным или рекурсивным приобретением мьютекса.
- Определено в:
-
lockInterruptiblyв интерфейсеLock - Исключения:
-
InterruptedException- если текущая нить прервана
tryLock
public boolean tryLock()
Приобретает мьютекс только в том случае, если он не удерживается другой нитью в момент вызова.
Приобретает мьютекс, если он не удерживается другой нитью, и возвращает значение true, устанавливая счётчик удержания мьютекса в единицу. Даже если этот мьютекс был настроен на использование политики честного порядка очереди, вызов tryLock() немедленно приобретёт мьютекс, если он доступен, вне зависимости от того, ожидают ли другие нити мьютекс. Это поведение «вторжения» может быть полезным в определённых ситуациях, хотя оно нарушает принцип честности. Если вы хотите соблюдать настройку честности для этого мьютекса, то используйте tryLock(0, TimeUnit.SECONDS) , который почти эквивалентен (он также обрабатывает прерывания).
Если текущая нить уже держит этот мьютекс, то счётчик удержания увеличивается на единицу, и метод возвращает true.
Если мьютекс удерживается другой нитью, то этот метод возвращает значение false.
- Определено в:
-
tryLockв интерфейсеLock - Возвращает:
-
trueесли мьютекс был свободен и был приобретён текущей нитью, или мьютекс уже был удерживаем текущей нитью; иfalseв противном случае
tryLock
public boolean tryLock(long timeout,
TimeUnit unit)
throws InterruptedException Приобретает мьютекс, если он не удерживается другой нитью в течение заданного времени ожидания, и текущая нить не была прервана.
Приобретает мьютекс, если он не удерживается другой нитью, и возвращает значение true, устанавливая счётчик удержания мьютекса в единицу. Если этот мьютекс был настроен на использование политики честного порядка очереди, то доступный мьютекс не будет приобретён, если другие нити ожидают мьютекс. Это в отличие от метода tryLock(). Если вам нужен временной tryLock , который позволяет вторгаться в честную очередь, то комбинируйте временной и безвременной варианты вместе:
if (lock.tryLock() ||
lock.tryLock(timeout, unit)) {
...
} Если текущая нить уже держит этот мьютекс, то счётчик удержания увеличивается на единицу, и метод возвращает true.
Если мьютекс удерживается другой нитью, то текущая нить отключается для планирования потоков и находится в ожидании, пока не произойдёт одно из трёх:
- Мьютекс приобретается текущей нитью; или
- Другая нить прерывает текущую нить; или
- Заданное время ожидания истекает
Если мьютекс приобретён, то возвращается значение true , и счётчик удержания устанавливается в единицу.
Если текущая нить:
- имеет свой флаг прерывания установленным в начале выполнения этого метода; или
- была прервана во время приобретения мьютекса,
InterruptedException, и флаг прерывания текущей нити сбрасывается. Если заданное время ожидания истекает, то возвращается значение false . Если время равно или меньше нуля, метод вообще не будет ожидать.
В этой реализации, поскольку этот метод является явной точкой прерывания, приоритет отдаётся обработке прерывания перед обычным или рекурсивным приобретением мьютекса, и перед сообщением об истечении времени ожидания.
- Определено в:
-
tryLockв интерфейсеLock - Параметры:
-
timeout- время ожидания мьютекса -
unit- единица измерения времени ожидания - Возвращает:
-
trueесли мьютекс был свободен и был приобретён текущей нитью, или мьютекс уже был удерживаем текущей нитью; иfalseесли время ожидания истекло до приобретения мьютекса - Исключения:
-
InterruptedException- если текущая нить прервана -
NullPointerException- если единица измерения времени равна null
unlock
public void unlock()
Пытается освободить этот мьютекс.
Если текущая нить является владельцем этого мьютекса, то счётчик удержания уменьшается. Если счётчик удержания теперь равен нулю, то мьютекс освобождается. Если текущая нить не является владельцем этого мьютекса, то генерируется исключение IllegalMonitorStateException.
- Определено в:
-
unlockв интерфейсеLock - Исключения:
-
IllegalMonitorStateException- если текущая нить не держит этот мьютекс
newCondition
public Condition newCondition()
Возвращает экземпляр Condition для использования с этим экземпляром Lock.
Возвращённый экземпляр Condition поддерживает те же методы, что и методы монитора Object (wait, notify и notifyAll) при использовании встроенного мьютекса монитора.
- Если этот мьютекс не удерживается, когда вызываются любые методы ожидания или сигнализации
Condition, то генерируется исключениеIllegalMonitorStateException. - Когда вызываются методы ожидания ожидания, мьютекс освобождается, и прежде чем они возвращаются, мьютекс вновь приобретается и счётчик удержания восстанавливается до значения, которое он имел при вызове метода.
- Если нить прерывается во время ожидания, то ожидание завершается, генерируется исключение
InterruptedException, и флаг прерывания нити сбрасывается. - Ожидающие нити сигнализируются в порядке очереди FIFO.
- Порядок повторного приобретения мьютекса нитями, возвращающимися из методов ожидания, такой же, как у нитей, которые первоначально приобретали мьютекс, который в качестве значения по умолчанию не определён, но для мьютексов с честностью отдаётся предпочтение тем нитям, которые дольше всего ожидают.
- Определено в:
-
newConditionв интерфейсеLock - Возвращает:
- объект Condition
getHoldCount
public int getHoldCount()
Запрашивает количество удержаний этого мьютекса текущей нитью.
У нити есть удержание мьютекса для каждого действия приобретения мьютекса, которое не соответствует действию освобождения.
Информация о счётчике удержаний обычно используется только для тестирования и отладки. Например, если определённый фрагмент кода не должен быть выполнен, если мьютекс уже удерживается, то можно утверждать это:
class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert lock.getHoldCount() == 0;
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}
- Возвращает:
- количество удержаний этого мьютекса текущей нитью или ноль, если этот мьютекс не удерживается текущей нитью
isHeldByCurrentThread
public boolean isHeldByCurrentThread()
Запрашивает, удерживается ли этот мьютекс текущей нитью.
Аналогично методу Thread.holdsLock(Object) для встроенных мьютексов монитора, этот метод обычно используется для отладки и тестирования. Например, метод, который должен вызываться только при удержании мьютекса, может утверждать, что это так:
class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert lock.isHeldByCurrentThread();
// ... method body
}
} Также его можно использовать, чтобы убедиться, что рекурсивный мьютекс используется нерекурсивным способом, например:
class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert !lock.isHeldByCurrentThread();
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}
- Возвращает:
-
trueесли текущая нить удерживает этот мьютекс иfalseв противном случае
isLocked
public boolean isLocked()
Запрашивает, удерживается ли этот мьютекс какой-либо нитью. Этот метод предназначен для использования при мониторинге состояния системы, а не для управления синхронизацией.
- Возвращает:
-
trueесли какой-либо поток удерживает этот мьютекс иfalseв противном случае
isFair
public final boolean isFair()
Возвращает true , если для этого мьютекса установлена честность.
- Возвращает:
-
trueесли для этого мьютекса установлена честность
getOwner
protected Thread getOwner()
Возвращает поток, который в данный момент владеет этим замком, или null если им никто не владеет. Когда этот метод вызывается потоком, который не является владельцем, возвращаемое значение отражает приблизительное текущее состояние замка. Например, владелец может временно null даже если есть потоки, пытающиеся получить замок, но ещё не сделавшие этого. Этот метод предназначен для облегчения создания подклассов, предоставляющих более широкие возможности мониторинга замка.
- Возвращает:
- владелец, или
nullесли им никто не владеет
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()
Возвращает строку, идентифицирующую этот замок, а также его состояние. Состояние, в скобках, содержит либо строку "Unlocked" , либо строку "Locked by" , за которой следует имя владеющего потока.
© 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.