Класс ReentrantLock
- Все реализованные интерфейсы:
-
Serializable,Lock
public class ReentrantLock extends Object implements Lock, Serializable
Lock с тем же базовым поведением и семантикой, что и неявный мониторный замок, доступ к которому осуществляется с помощью synchronized методов и операторов, но с расширенными возможностями. A 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<Thread> |
getQueuedThreads() |
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения этой блокировки. |
final int |
getQueueLength() |
Возвращает приблизительное количество потоков, ожидающих получения этой блокировки. |
protected Collection<Thread> |
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();
}
}
}
- Возвращает:
-
trueесли текущий поток удерживает этот замок, иfalseв противном случае
isLocked
public boolean isLocked()
- Возвращает:
-
trueесли какой-либо поток удерживает этот замок иfalseв противном случае
isFair
public final boolean isFair()
true , если для этого замка установлено значение fairness (справедливость).- Возвращает:
-
trueесли для этого замка установлено значение fairness (справедливость)
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" , за которой следует имя владеющего потока.- Переопределяет:
-
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/ReentrantLock.html