Класс 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 из методов блокировки.
- С тех пор:
- 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.
- Возвращает:
-
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.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/locks/ReentrantLock.html