Класс LockSupport
public class LockSupport extends Object
Этот класс ассоциирует с каждым использующим его потоком разрешение (в смысле класса Semaphore). Вызов park вернёт значение немедленно, если разрешение доступно, потребляя его в процессе; в противном случае он может заблокироваться. Вызов unpark делает разрешение доступным, если оно не было доступно ранее. (В отличие от семафоров, разрешения не накапливаются. Их не может быть больше одного.) Надежное использование требует использования переменных volatile (или атомных) для управления тем, когда следует остановить или разблокировать поток. Порядок вызовов этих методов сохраняется относительно доступа к переменным volatile, но не обязательно к доступам к переменным, не являющимся volatile.
Методы park и unpark обеспечивают эффективные средства блокировки и разблокировки потоков, не сталкивающиеся с проблемами, из-за которых устаревшие методы Thread.suspend и Thread.resume непригодны для таких целей: Гонки между одним потоком, вызывающим park, и другим потоком, пытающимся unpark его, сохранят жизнеспособность благодаря разрешению. Кроме того, park вернётся, если поток вызывающего был прерван, и поддерживаются версии с таймаутами. Метод park также может вернуться в любое другое время, «без причины», поэтому, как правило, он должен вызываться в цикле, который повторно проверяет условия при возвращении. В этом смысле park служит оптимизацией «занятого ожидания», которое не тратит так много времени на ожидание, но должно быть сопряжено с unpark для достижения эффективности.
Три формы park также поддерживают параметр объекта blocker. Этот объект записывается, пока поток заблокирован, чтобы позволить средствам мониторинга и диагностики идентифицировать причины блокировки потоков. (Эти средства могут получить доступ к блокировщикам с помощью метода getBlocker(Thread).) Сильно рекомендуется использовать эти формы вместо исходных форм без этого параметра. Обычный аргумент, который следует передавать в качестве blocker в реализации блокировки, это this.
Эти методы предназначены для использования в качестве инструментов для создания утилит синхронизации более высокого уровня и сами по себе не пригодны для большинства приложений управления конкурентностью. Метод park предназначен для использования только в конструкциях вида:
while (!canProceed()) {
// ensure request to unpark is visible to other threads
...
LockSupport.park(this);
} где никакие действия потока, публикующего запрос на разблокировку, до вызова park, не предполагают блокировку или ожидание. Поскольку только одно разрешение ассоциируется с каждым потоком, любое промежуточное использование park, включая неявное через загрузку классов, может привести к бездействию потока (потерянная разблокировка). Пример использования. Вот эскиз класса блокировки «первый пришёл — первый обслужен», не реентерабельный:
class FIFOMutex {
private final AtomicBoolean locked = new AtomicBoolean(false);
private final Queue<Thread> waiters
= new ConcurrentLinkedQueue<>();
public void lock() {
boolean wasInterrupted = false;
// publish current thread for unparkers
waiters.add(Thread.currentThread());
// Block while not first in queue or cannot acquire lock
while (waiters.peek() != Thread.currentThread() ||
!locked.compareAndSet(false, true)) {
LockSupport.park(this);
// ignore interrupts while waiting
if (Thread.interrupted())
wasInterrupted = true;
}
waiters.remove();
// ensure correct interrupt status on return
if (wasInterrupted)
Thread.currentThread().interrupt();
}
public void unlock() {
locked.set(false);
LockSupport.unpark(waiters.peek());
}
static {
// Reduce the risk of "lost unpark" due to classloading
Class<?> ensureLoaded = LockSupport.class;
}
}
- С:
- 1.5
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
static Object |
getBlocker |
Возвращает объект блокировщика, предоставленный в последнем вызове метода park, который ещё не разблокировал, или null, если не заблокирован. |
static void |
park() |
Отключает текущий поток для целей планирования потоков, если разрешение недоступно. |
static void |
park |
Отключает текущий поток для целей планирования потоков, если разрешение недоступно. |
static void |
parkNanos |
Отключает текущий поток для целей планирования потоков в течение заданного времени ожидания, если разрешение недоступно. |
static void |
parkNanos |
Отключает текущий поток для целей планирования потоков в течение заданного времени ожидания, если разрешение недоступно. |
static void |
parkUntil |
Отключает текущий поток для целей планирования потоков до заданного крайнего срока, если разрешение недоступно. |
static void |
parkUntil |
Отключает текущий поток для целей планирования потоков до заданного крайнего срока, если разрешение недоступно. |
static void |
setCurrentBlocker |
Устанавливает объект, который будет возвращён вызовами getBlocker для текущего потока. |
static void |
unpark |
Делает разрешение доступным для данного потока, если оно не было доступно ранее. |
Подробное описание методов
setCurrentBlocker
public static void setCurrentBlocker(Object blocker)
getBlocker для текущей нити. Этот метод можно использовать перед вызовом версии метода park() без аргументов из непубличных объектов, позволяя получить более полезные диагностические данные или сохраняя совместимость с предыдущими реализациями методов блокировки. Предыдущие значения блокировщика не восстанавливаются автоматически после блокировки. Чтобы получить эффекты park(b}, используйте
setCurrentBlocker(b); park(); setCurrentBlocker(null);
- Параметры:
-
blocker- объект блокировщика - С:
- 14
unpark
public static void unpark(Thread thread)
park , то она будет разблокирована. В противном случае её следующий вызов park гарантированно не заблокируется. Данная операция не гарантирует никакого эффекта, если заданная нить не была запущена.- Параметры:
-
thread- нить для разблокирования илиnull, в этом случае операция не оказывает никакого эффекта
park
public static void park(Object blocker)
Если разрешение доступно, то оно используется, и вызов возвращает значение немедленно; в противном случае текущая нить отключается от планирования и находится в спящем состоянии до тех пор, пока не произойдёт одно из трёх событий:
- Другая нить вызывает
unparkс текущей нитью в качестве целевой нити; или - Другая нить прерывает текущую нить; или
- Вызов возвращает неожиданно (без причины).
Данный метод не сообщает, какое из этих событий привело к возвращению. Вызывающий код должен повторно проверить условия, которые привели к остановке нити в первую очередь. Вызывающий код может также определить, например, статус прерывания нити после возвращения.
- Параметры:
-
blocker- объект синхронизации, отвечающий за остановку этой нити - С:
- 1.6
parkNanos
public static void parkNanos(Object blocker, long nanos)
Если указанное время ожидания равно нулю или отрицательно, метод ничего не делает. В противном случае, если разрешение доступно, то оно используется, и вызов возвращает значение немедленно; в противном случае текущая нить отключается от планирования и находится в спящем состоянии до одного из четырёх событий:
- Другая нить вызывает
unparkс текущей нитью в качестве целевой нити; или - Другая нить прерывает текущую нить; или
- Указанное время ожидания истекает; или
- Вызов возвращает неожиданно (без причины).
Данный метод не сообщает, какое из этих событий привело к возвращению. Вызывающий код должен повторно проверить условия, которые привели к остановке нити в первую очередь. Вызывающий код может также определить, например, статус прерывания нити или истекшее время после возвращения.
- Параметры:
-
blocker- объект синхронизации, отвечающий за остановку этой нити -
nanos- максимальное количество наносекунд ожидания - С:
- 1.6
parkUntil
public static void parkUntil(Object blocker, long deadline)
Если разрешение доступно, то оно используется, и вызов возвращает значение немедленно; в противном случае текущая нить отключается от планирования и находится в спящем состоянии до одного из четырёх событий:
- Другая нить вызывает
unparkс текущей нитью в качестве целевой нити; или - Другая нить прерывает текущую нить; или
- Указанный крайний срок истекает; или
- Вызов возвращает неожиданно (без причины).
Данный метод не сообщает, какое из этих событий привело к возвращению. Вызывающий код должен повторно проверить условия, которые привели к остановке нити в первую очередь. Вызывающий код может также определить, например, статус прерывания нити или текущее время при возвращении.
- Параметры:
-
blocker- объект синхронизации, отвечающий за остановку этой нити -
deadline- абсолютное время, в миллисекундах от эпохи, до которого следует ждать - С:
- 1.6
getBlocker
public static Object getBlocker(Thread t)
- Параметры:
-
t- нить - Возвращает:
- объект блокировщика
- Исключения:
-
NullPointerException- если аргумент равен null - С:
- 1.6
park
public static void park()
Если разрешение доступно, то оно используется, и вызов возвращает значение немедленно; в противном случае текущая нить отключается от планирования и находится в спящем состоянии до тех пор, пока не произойдёт одно из трёх событий:
- Другая нить вызывает
unparkс текущей нитью в качестве целевой нити; или - Другая нить прерывает текущую нить; или
- Вызов возвращает неожиданно (без причины).
Данный метод не сообщает, какое из этих событий привело к возвращению. Вызывающий код должен повторно проверить условия, которые привели к остановке нити в первую очередь. Вызывающий код может также определить, например, статус прерывания нити после возвращения.
parkNanos
public static void parkNanos(long nanos)
Если указанное время ожидания равно нулю или отрицательно, метод ничего не делает. В противном случае, если разрешение доступно, то оно используется, и вызов возвращает значение немедленно; в противном случае текущая нить отключается от планирования и находится в спящем состоянии до одного из четырёх событий:
- Другая нить вызывает
unparkс текущей нитью в качестве целевой нити; или - Другая нить прерывает текущую нить; или
- Указанное время ожидания истекает; или
- Вызов возвращает неожиданно (без причины).
Данный метод не сообщает, какое из этих событий привело к возвращению. Вызывающий код должен повторно проверить условия, которые привели к остановке нити в первую очередь. Вызывающий код может также определить, например, статус прерывания нити или истекшее время после возвращения.
- Параметры:
-
nanos- максимальное количество наносекунд ожидания
parkUntil
public static void parkUntil(long deadline)
Если разрешение доступно, то оно используется, и вызов возвращает значение немедленно; в противном случае текущая нить отключается от планирования и находится в спящем состоянии до одного из четырёх событий:
- Другая нить вызывает
unparkс текущей нитью в качестве целевой нити; или - Другая нить прерывает текущую нить; или
- Указанный крайний срок истекает; или
- Вызов возвращает неожиданно (без причины).
Данный метод не сообщает, какое из этих событий привело к возвращению. Вызывающий код должен повторно проверить условия, которые привели к остановке нити в первую очередь. Вызывающий код может также определить, например, статус прерывания нити или текущее время при возвращении.
- Параметры:
-
deadline- абсолютное время, в миллисекундах от эпохи, до которого следует ждать
© 1993, 2023, 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/21/docs/api/java.base/java/util/concurrent/locks/LockSupport.html