Класс 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() |
Пытается освободить эту блокировку. |
Подробное описание конструкторов
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.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/locks/ReentrantLock.html