Класс 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 исключениям при вызовах методов блокировки.
- С момента:
- 1.5
- См. также:
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
ReentrantLock() |
Создаёт экземпляр ReentrantLock. |
ReentrantLock |
Создаёт экземпляр ReentrantLock с заданной политикой справедливости. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
int |
getHoldCount() |
Запрашивает количество удержаний этого замка текущим потоком. |
protected Thread |
getOwner() |
Возвращает поток, который в настоящее время владеет этим замком, или null если не владеет. |
protected Collection |
getQueuedThreads() |
Возвращает коллекцию, содержащую потоки, которые могут ожидать приобретения этого замка. |
final int |
getQueueLength() |
Возвращает оценку числа потоков, ожидающих приобретения этого замка. |
protected Collection |
getWaitingThreads |
Возвращает коллекцию, содержащую те потоки, которые могут ожидать на заданном условии, связанном с этим замком. |
int |
getWaitQueueLength |
Возвращает оценку числа потоков, ожидающих на заданном условии, связанном с этим замком. |
final boolean |
hasQueuedThread |
Запрашивает, ожидает ли заданный поток приобретения этого замка. |
final boolean |
hasQueuedThreads() |
Запрашивает, ожидают ли какие-либо потоки приобретения этого замка. |
boolean |
hasWaiters |
Запрашивает, ожидают ли какие-либо потоки на заданном условии, связанном с этим замком. |
final boolean |
isFair() |
Возвращает true если для этого замка справедливость установлена в true. |
boolean |
isHeldByCurrentThread() |
Запрашивает, удерживает ли текущий поток этот замок. |
boolean |
isLocked() |
Запрашивает, удерживает ли этот замок какой-либо поток. |
void |
lock() |
Приобретает замок. |
void |
lockInterruptibly() |
Приобретает замок, если текущий поток не прерван. |
Condition |
newCondition() |
|
String |
toString() |
Возвращает строку, идентифицирующую этот замок, а также его состояние. |
boolean |
tryLock() |
Приобретает замок только в том случае, если им не владеет другой поток на момент вызова. |
boolean |
tryLock |
Приобретает замок, если им не владеет другой поток в течение заданного времени ожидания, и текущий поток не прерван. |
void |
unlock() |
Пытается освободить этот замок. |
Подробное описание конструкторов
ReentrantLock
public ReentrantLock()
ReentrantLock. Это эквивалентно использованию ReentrantLock(false).ReentrantLock
public ReentrantLock(boolean fair)
ReentrantLock с заданной политикой честности.- Параметры:
-
fair-trueесли для этого замка должна использоваться политика справедливого порядка
Подробное описание методов
lock
public void lock()
Приобретает замок, если он не удерживается другой нитью, и возвращается немедленно, устанавливая счётчик удержания замка в один.
Если текущая нить уже удерживает замок, то счётчик удержания увеличивается на один, и метод возвращается немедленно.
Если замок удерживается другой нитью, то текущая нить отключается для целей планирования потоков и находится в спящем состоянии до тех пор, пока замок не будет приобретён, в этот момент счётчик удержания замка устанавливается в один.
- Определено в:
-
lockв интерфейсе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 {
final 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 {
final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert lock.isHeldByCurrentThread();
// ... method body
}
} Он также может использоваться для обеспечения того, что реентерабельный замок используется нереентерабельным способом, например:
class X {
final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert !lock.isHeldByCurrentThread();
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}
- Returns:
-
trueесли текущий поток удерживает этот замок иfalseв противном случае
isLocked
public boolean isLocked()
- Returns:
-
trueесли какой-либо поток удерживает этот замок иfalseв противном случае
isFair
public final boolean isFair()
true если для этого замка установлена справедливость.- Returns:
-
trueесли для этого замка установлена справедливость
getOwner
protected Thread getOwner()
null если он не владеет. Когда этот метод вызывается потоком, который не является владельцем, возвращаемое значение отражает приблизительное состояние текущего замка. Например, владелец может временно null даже если есть потоки, пытающиеся получить замок, но еще не сделали этого. Этот метод предназначен для облегчения построения подклассов, которые обеспечивают более расширенные средства мониторинга замков.- Returns:
- владелец или
nullесли не владеет
hasQueuedThreads
public final boolean hasQueuedThreads()
true возвращение не гарантирует, что какой-либо другой поток когда-либо получит этот замок. Этот метод предназначен в основном для мониторинга состояния системы.- Returns:
-
trueесли могут быть другие потоки, ожидающие получения замка
hasQueuedThread
public final boolean hasQueuedThread(Thread thread)
true возвращение не гарантирует, что этот поток когда-либо получит этот замок. Этот метод предназначен в основном для мониторинга состояния системы.- Parameters:
-
thread- поток - Returns:
-
trueесли заданный поток находится в очереди, ожидая этого замка - Throws:
-
NullPointerException- если поток равен null
getQueueLength
public final int getQueueLength()
- Returns:
- приблизительное количество потоков, ожидающих этого замка
getQueuedThreads
protected Collection<Thread> getQueuedThreads()
- Returns:
- коллекция потоков
hasWaiters
public boolean hasWaiters(Condition condition)
true возвращение не гарантирует, что в будущем signal разбудит какие-либо потоки. Этот метод предназначен в основном для мониторинга состояния системы.- Parameters:
-
condition- условие - Returns:
-
trueесли есть ожидающие потоки - Throws:
-
IllegalMonitorStateException- если этот замок не удерживается -
IllegalArgumentException- если данное условие не связано с этим замком -
NullPointerException- если условие равно null
getWaitQueueLength
public int getWaitQueueLength(Condition condition)
- Parameters:
-
condition- условие - Returns:
- приблизительное количество ожидающих потоков
- Throws:
-
IllegalMonitorStateException- если этот замок не удерживается -
IllegalArgumentException- если данное условие не связано с этим замком -
NullPointerException- если условие равно null
getWaitingThreads
protected Collection<Thread> getWaitingThreads(Condition condition)
- Parameters:
-
condition- условие - Returns:
- коллекция потоков
- Throws:
-
IllegalMonitorStateException- если этот замок не удерживается -
IllegalArgumentException- если данное условие не связано с этим замком -
NullPointerException- если условие равно null
toString
public String toString()
"Unlocked" или строку "Locked by" за которой следует имя владеющего потока.- Overrides:
-
toStringв классеObject - Returns:
- строка, идентифицирующая этот замок, а также его состояние блокировки
© 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/ReentrantLock.html