Класс 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, если для этой блокировки включена справедливость. |
boolean |
isHeldByCurrentThread() |
Проверяет, удерживает ли текущий поток эту блокировку. |
boolean |
isLocked() |
Проверяет, удерживается ли эта блокировка каким-либо потоком. |
void |
lock() |
Захватывает блокировку. |
void |
lockInterruptibly() |
Захватывает блокировку, если текущий поток не прерван. |
Condition |
newCondition() |
|
String |
toString() |
Возвращает строку, идентифицирующую эту блокировку, а также её состояние. |
boolean |
tryLock() |
Захватывает блокировку, только если на момент вызова она не удерживается другим потоком. |
boolean |
tryLock |
Захватывает блокировку, если в течение указанного времени ожидания она не удерживается другим потоком и текущий поток не был прерван. |
void |
unlock() |
Пытается освободить эту блокировку. |
Методы, объявленные в классе Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait | Модификатор и тип | Метод | Описание |
|---|---|---|
protected Object |
clone() |
Создаёт и возвращает копию этого объекта. |
boolean |
equals |
Указывает, равен ли другой объект этому объекту. |
protected void |
finalize() |
Устарел и подлежит удалению: этот элемент API планируется удалить в будущей версии. Финализация устарела и подлежит удалению в одном из будущих выпусков. |
final Class |
getClass() |
Возвращает класс времени выполнения этого Object. |
int |
hashCode() |
Возвращает значение хеш-кода для этого объекта. |
final void |
notify() |
Пробуждает один поток, ожидающий на мониторе этого объекта. |
final void |
notifyAll() |
Пробуждает все потоки, ожидающие на мониторе этого объекта. |
final void |
wait() |
Заставляет текущий поток ждать до пробуждения, обычно в результате уведомления или прерывания. |
final void |
wait |
Заставляет текущий поток ждать до пробуждения, обычно в результате уведомления или прерывания, либо до истечения заданного промежутка реального времени. |
final void |
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
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, если для этой блокировки включена справедливость.- Возвращает:
-
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, 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.