Класс ReentrantLock
- Все реализуемые интерфейсы:
-
Serializable,Lock
public class ReentrantLock extends Object implements Lock, Serializable
Lock с тем же базовым поведением и семантикой, что и неявный мониторный замок, доступный с помощью synchronized методов и операторов, но с расширенными возможностями. ReentrantLock принадлежит потоку, который последний успешно заблокировал его, но еще не разблокировал. Поток, вызывающий lock, вернётся, успешно получив замок, если замок не принадлежит другому потоку. Метод вернётся немедленно, если текущий поток уже владеет замком. Это можно проверить с помощью методов isHeldByCurrentThread() и getHoldCount().
Конструктор этого класса принимает необязательный параметр справедливости. При установке true, при возникновении конфликта, замки предоставляют доступ потоку, который дольше всего ожидает. В противном случае этот замок не гарантирует какой-либо определённый порядок доступа. Программы, использующие справедливые замки, доступные многим потокам, могут демонстрировать более низкую общую производительность (т. е., медленнее; часто намного медленнее), чем те, которые используют значение по умолчанию, но имеют меньшие вариации во времени получения замков и гарантируют отсутствие голодания. Однако справедливость замков не гарантирует справедливость планирования потоков. Таким образом, один из многих потоков, использующих справедливый замок, может получить его несколько раз подряд, в то время как другие активные потоки не прогрессируют и в настоящее время не владеют замком. Обратите также внимание, что безадресное tryLock() не учитывает параметр справедливости. Он будет успешным, если замок доступен, даже если другие потоки ожидают.
Рекомендуется всегда немедленно следовать вызову lock с блоком try и всегда немедленно вызывать unlock в качестве первого оператора в блоке finally, как показано ниже:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // lock() as the last statement before the try block
try {
// ... method body
} finally {
lock.unlock(); // unlock() as the first statement in the finally block
}
}
} Помимо реализации интерфейса 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() |
Попытка разблокировать этот замок. |
Конструктор Details
ReentrantLock
public ReentrantLock()
ReentrantLock. Это эквивалентно использованию ReentrantLock(false).ReentrantLock
public ReentrantLock(boolean fair)
ReentrantLock с заданной политикой справедливости.- Параметры:
-
fair-true, если для этой блокировки должна использоваться политика справедливого порядка
Методы Details
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
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", за которой следует имя владеющего потока.
© 1993, 2025, 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://download.java.net/java/early_access/jdk24/docs/api/java.base/java/util/concurrent/locks/ReentrantLock.html