Класс Semaphore
- java.lang.Object
-
- java.util.concurrent.Semaphore
- Все реализуемые интерфейсы:
- Serializable
public class Semaphore extends Object implements Serializable
Счетный семафор. По концепции, семафор поддерживает набор разрешений. Каждый acquire() блокируется, если необходимо, до тех пор, пока разрешение не станет доступным, а затем берет его. Каждый release() добавляет разрешение, потенциально разблокируя заблокированный запрос. Однако фактические объекты разрешений не используются; семафор просто хранит счетчик доступного количества и действует соответственно.
Семафоры часто используются для ограничения количества потоков, которые могут получить доступ к некоторому (физическому или логическому) ресурсу. Например, вот класс, который использует семафор для управления доступом к пулу элементов:
class Pool {
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
} Перед получением элемента каждый поток должен получить разрешение от семафора, гарантируя, что элемент доступен для использования. Когда поток закончил с элементом, он возвращается в пул, и разрешение возвращается семафору, позволяя другому потоку получить этот элемент. Обратите внимание, что никакой блокировки синхронизации не удерживается при вызове acquire(), так как это помешало бы вернуть элемент в пул. Семафор инкапсулирует необходимую синхронизацию для ограничения доступа к пулу, отдельно от любой синхронизации, необходимой для поддержания согласованности самого пула.
Семафор, инициализированный единицей и используемый таким образом, что у него доступно не более одного разрешения, может служить блокировкой взаимного исключения. Это более известно как двоичный семафор, потому что он имеет только два состояния: одно разрешение доступно или ноль разрешений доступно. При использовании таким образом двоичный семафор обладает свойством (в отличие от многих Lock реализаций), что «блокировка» может быть освобождена потоком, отличным от владельца (поскольку семафоры не имеют понятия о владении). Это может быть полезно в некоторых специализированных контекстах, таких как восстановление тупика.
Конструктор этого класса необязательно принимает параметр справедливости. Если он установлен в false, этот класс не дает никаких гарантий относительно порядка, в котором потоки получают разрешения. В частности, разрешается вторжение, то есть потоку, вызывающему acquire(), может быть выделено разрешение раньше потока, который ожидал - логически новый поток помещает себя в начало очереди ожидающих потоков. Когда справедливость установлена в true, семафор гарантирует, что потоки, вызывающие любой из acquire методов, выбираются для получения разрешений в том порядке, в котором их вызов этих методов был обработан (первый вошел, первый вышел; FIFO). Обратите внимание, что упорядочение FIFO обязательно применяется к определенным внутренним точкам выполнения в этих методах. Таким образом, один поток может вызвать acquire перед другим, но достичь точки упорядочения после другого, и аналогично при возвращении из метода. Также обратите внимание, что методы tryAcquire без учета времени не учитывают настройку справедливости, а будут брать любые доступные разрешения.
В общем случае семафоры, используемые для управления доступом к ресурсам, должны быть инициализированы как справедливые, чтобы гарантировать, что ни один поток не лишен доступа к ресурсу. При использовании семафоров для других типов управления синхронизацией преимущества производительности несправедливого упорядочения часто перевешивают соображения справедливости.
Этот класс также предоставляет удобные методы для acquire и release нескольких разрешений за раз. Будьте осторожны, так как существует повышенный риск неопределенного отсрочки при использовании этих методов без установки справедливости на true.
Эффекты согласованности памяти: Действия в потоке перед вызовом метода «release», например, release() предшествуют действиям, следующим за успешным методом «acquire», например, acquire() в другом потоке.
- C:
- 1.5
- См. также:
- Сериализованная форма
Конструкторы
| Конструктор и описание |
|---|
Semaphore(int permits) Создает |
Semaphore(int permits,
boolean fair) Создает |
Методы
| Модификатор и тип | Метод и описание |
|---|---|
void |
acquire() Получает разрешение из этого семафора, блокируя до тех пор, пока оно не станет доступным, или поток не будет прерван. |
void |
acquire(int permits) Получает заданное количество разрешений из этого семафора, блокируя до тех пор, пока все они не станут доступными, или поток не будет прерван. |
void |
acquireUninterruptibly() Получает разрешение из этого семафора, блокируя до тех пор, пока оно не станет доступным. |
void |
acquireUninterruptibly(int permits) Получает заданное количество разрешений из этого семафора, блокируя до тех пор, пока все они не станут доступными. |
int |
availablePermits() Возвращает текущее количество доступных разрешений в этом семафоре. |
int |
drainPermits() Получает и возвращает все разрешения, которые немедленно доступны. |
protected Collection<Thread> |
getQueuedThreads() Возвращает коллекцию, содержащую потоки, которые могут ожидать получения. |
int |
getQueueLength() Возвращает оценку числа потоков, ожидающих получения. |
boolean |
hasQueuedThreads() Определяет, ожидают ли какие-либо потоки получения. |
boolean |
isFair() Возвращает |
protected void |
reducePermits(int reduction) Уменьшает количество доступных разрешений на указанное уменьшение. |
void |
release() Освобождает разрешение, возвращая его в семафор. |
void |
release(int permits) Освобождает заданное количество разрешений, возвращая их в семафор. |
String |
toString() Возвращает строку, идентифицирующую этот семафор, а также его состояние. |
boolean |
tryAcquire() Получает разрешение из этого семафора, только если оно доступно в момент вызова. |
boolean |
tryAcquire(int permits) Получает заданное количество разрешений из этого семафора, только если все они доступны в момент вызова. |
boolean |
tryAcquire(int permits,
long timeout,
TimeUnit unit) Получает заданное количество разрешений из этого семафора, если все они станут доступными в течение заданного времени ожидания, и текущий поток не был прерван. |
boolean |
tryAcquire(long timeout,
TimeUnit unit) Получает разрешение из этого семафора, если оно станет доступным в течение заданного времени ожидания, и текущий поток не был прерван. |
Методы, унаследованные от класса java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait Конструкторы
Semaphore
public Semaphore(int permits)
Создаёт Semaphore с заданным количеством разрешений и настройкой справедливости nonfair.
- Параметры:
-
permits- начальное количество доступных разрешений. Это значение может быть отрицательным, в этом случае, прежде чем какие-либо разрешения будут предоставлены, должны произойти освобождения.
Semaphore
public Semaphore(int permits,
boolean fair) Создаёт Semaphore с заданным количеством разрешений и заданной настройкой справедливости.
- Параметры:
-
permits- начальное количество доступных разрешений. Это значение может быть отрицательным, в этом случае, прежде чем какие-либо разрешения будут предоставлены, должны произойти освобождения. -
fair-trueесли этот семафор гарантирует предоставление разрешений в порядке очереди при конкуренции, иначеfalse
Методы
acquire
public void acquire()
throws InterruptedException Приобретает разрешение из этого семафора, блокируя до тех пор, пока оно не станет доступным, или поток не будет прерван.
Приобретает разрешение, если оно доступно, и возвращается немедленно, уменьшая количество доступных разрешений на единицу.
Если разрешение недоступно, текущий поток становится неактивным для целей планирования потоков и находится в спящем состоянии, пока не произойдёт одно из двух событий:
- Какой-то другой поток вызывает метод
release()для этого семафора, и текущий поток следующим должен получить разрешение; - Какой-то другой поток прерывает текущий поток.
Если текущий поток:
- имеет установленный флаг прерывания при входе в этот метод; или
- был прерван во время ожидания разрешения,
InterruptedException, и флаг прерывания текущего потока сбрасывается.- Выбрасывает:
-
InterruptedException- если текущий поток прерван
acquireUninterruptibly
public void acquireUninterruptibly()
Приобретает разрешение из этого семафора, блокируя до тех пор, пока оно не станет доступным.
Приобретает разрешение, если оно доступно, и возвращается немедленно, уменьшая количество доступных разрешений на единицу.
Если разрешение недоступно, текущий поток становится неактивным для целей планирования потоков и находится в спящем состоянии, пока какой-то другой поток не вызовет метод release() для этого семафора, и текущий поток следующим должен получить разрешение.
Если текущий поток прерывается во время ожидания разрешения, он продолжает ждать, но время, в которое поток получает разрешение, может измениться по сравнению со временем, которое он бы получил, если бы прерывания не произошло. Когда поток возвращается из этого метода, его флаг прерывания будет установлен.
tryAcquire
public boolean tryAcquire()
Приобретает разрешение из этого семафора, только если оно доступно в момент вызова.
Приобретает разрешение, если оно доступно, и возвращается немедленно со значением true, уменьшая количество доступных разрешений на единицу.
Если разрешение недоступно, этот метод возвращается немедленно со значением false.
Даже если этот семафор настроен на использование политики справедливого порядка, вызов tryAcquire() немедленно приобретёт разрешение, если оно доступно, независимо от того, ожидают ли в данный момент другие потоки. Это поведение «вторжения» может быть полезным в определённых ситуациях, даже если оно нарушает справедливость. Если вы хотите соблюдать настройку справедливости, используйте tryAcquire(0, TimeUnit.SECONDS) , который почти эквивалентен (он также обнаруживает прерывание).
- Возвращает:
-
trueесли разрешение было приобретено иfalseв противном случае
tryAcquire
public boolean tryAcquire(long timeout,
TimeUnit unit)
throws InterruptedException Приобретает разрешение из этого семафора, если оно становится доступным в течение заданного времени ожидания, и текущий поток не был прерван.
Приобретает разрешение, если оно доступно, и возвращается немедленно со значением true, уменьшая количество доступных разрешений на единицу.
Если разрешение недоступно, текущий поток становится неактивным для целей планирования потоков и находится в спящем состоянии, пока не произойдёт одно из трёх событий:
- Какой-то другой поток вызывает метод
release()для этого семафора, и текущий поток следующим должен получить разрешение; - Какой-то другой поток прерывает текущий поток;
- Заданное время ожидания истекает.
Если разрешение приобретено, возвращается значение true.
Если текущий поток:
- имеет установленный флаг прерывания при входе в этот метод; или
- был прерван во время ожидания приобретения разрешения,
InterruptedException, и флаг прерывания текущего потока сбрасывается. Если заданное время ожидания истекло, возвращается значение false. Если время равно или меньше нуля, метод вообще не будет ждать.
- Параметры:
-
timeout- максимальное время ожидания разрешения -
unit- единица измерения времени для аргументаtimeout - Возвращает:
-
trueесли разрешение было приобретено иfalseесли время ожидания истекло, прежде чем разрешение было приобретено - Выбрасывает:
-
InterruptedException- если текущий поток прерван
release
public void release()
Освобождает разрешение, возвращая его семафору.
Освобождает разрешение, увеличивая количество доступных разрешений на единицу. Если какие-либо потоки пытаются приобрести разрешение, выбирается один, и ему выдаётся освобождённое разрешение. Этот поток снова активируется для целей планирования потоков.
Нет требования, чтобы поток, который освобождает разрешение, должен был приобрести это разрешение, вызвав acquire(). Правильное использование семафора устанавливается соглашением по программированию в приложении.
acquire
public void acquire(int permits)
throws InterruptedException Приобретает заданное количество разрешений из этого семафора, блокируя до тех пор, пока все не станут доступными, или поток не будет прерван.
Приобретает заданное количество разрешений, если они доступны, и возвращается немедленно, уменьшая количество доступных разрешений на заданную величину.
Если недостаточно разрешений, текущий поток становится неактивным для целей планирования потоков и находится в спящем состоянии, пока не произойдёт одно из двух событий:
- Какой-то другой поток вызывает один из методов
releaseдля этого семафора, текущий поток следующим должен получить разрешения, и количество доступных разрешений удовлетворяет этому запросу; - Какой-то другой поток прерывает текущий поток.
Если текущий поток:
- имеет установленный флаг прерывания при входе в этот метод; или
- был прерван во время ожидания разрешения,
InterruptedException, и флаг прерывания текущего потока сбрасывается. Любые разрешения, которые должны были быть назначены этому потоку, вместо этого назначаются другим потокам, пытающимся приобрести разрешения, как если бы разрешения были предоставлены вызовом release().- Параметры:
-
permits- количество разрешений для приобретения - Выбрасывает:
-
InterruptedException- если текущий поток прерван -
IllegalArgumentException- еслиpermitsотрицательно
acquireUninterruptibly
public void acquireUninterruptibly(int permits)
Приобретает заданное количество разрешений из этого семафора, блокируя до тех пор, пока все не станут доступными.
Приобретает заданное количество разрешений, если они доступны, и возвращается немедленно, уменьшая количество доступных разрешений на заданную величину.
Если недостаточно разрешений, текущий поток становится неактивным для целей планирования потоков и находится в спящем состоянии, пока какой-то другой поток не вызовет один из методов release для этого семафора, текущий поток следующим должен получить разрешения и количество доступных разрешений удовлетворяет этому запросу.
Если текущий поток прерывается во время ожидания разрешений, он продолжает ждать, и его позиция в очереди не изменяется. Когда поток возвращается из этого метода, его флаг прерывания будет установлен.
- Параметры:
-
permits- количество разрешений для приобретения - Выбрасывает:
-
IllegalArgumentException- еслиpermitsотрицательно
tryAcquire
public boolean tryAcquire(int permits)
Приобретает заданное количество разрешений из этого семафора, только если все они доступны в момент вызова.
Приобретает заданное количество разрешений, если они доступны, и возвращается немедленно со значением true, уменьшая количество доступных разрешений на заданную величину.
Если недостаточно разрешений, этот метод возвращается немедленно со значением false, и количество доступных разрешений не изменяется.
Даже если этот семафор настроен на использование политики справедливого порядка, вызов tryAcquire немедленно приобретёт разрешения, если они доступны, независимо от того, ожидают ли другие потоки. Это поведение «вторжения» может быть полезным в определённых ситуациях, хотя оно нарушает справедливость. Если вы хотите соблюдать настройку справедливости, используйте tryAcquire(permits, 0, TimeUnit.SECONDS) , который почти эквивалентен (он также обнаруживает прерывание).
- Параметры:
-
permits- количество разрешений для приобретения - Возвращает:
-
trueесли разрешения были приобретены иfalseв противном случае - Выбрасывает:
-
IllegalArgumentException- еслиpermitsотрицательно
tryAcquire
public boolean tryAcquire(int permits,
long timeout,
TimeUnit unit)
throws InterruptedException Получает заданное количество разрешений от этого семафора, если все становятся доступными в течение заданного времени ожидания, и текущий поток не был прерван.
Получает заданное количество разрешений, если они доступны, и возвращает значение немедленно, с значением true, уменьшая количество доступных разрешений на указанную величину.
Если недостаточно разрешений, то текущий поток отключается для целей планирования потоков и находится в спящем режиме, пока не произойдёт одно из трёх событий:
- Другой поток вызывает один из методов
releaseдля этого семафора, текущий поток следующим должен получить разрешения, и количество доступных разрешений удовлетворяет этому запросу; или - Другой поток прерывает текущий поток; или
- Указанное время ожидания истекает.
Если разрешения получены, то возвращается значение true.
Если текущий поток:
- имеет свой флаг прерывания установлен при входе в этот метод; или
- бывает прерван во время ожидания получения разрешений,
InterruptedException, и флаг прерывания текущего потока сбрасывается. Любые разрешения, которые должны были быть назначены этому потоку, вместо этого назначаются другим потокам, пытающимся получить разрешения, как если бы разрешения были сделаны доступными вызовом release(). Если указанное время ожидания истекает, то возвращается значение false. Если время меньше или равно нулю, метод вообще не будет ожидать. Любые разрешения, которые должны были быть назначены этому потоку, вместо этого назначаются другим потокам, пытающимся получить разрешения, как если бы разрешения были сделаны доступными вызовом release().
- Параметры:
-
permits- количество разрешений для получения -
timeout- максимальное время ожидания разрешений -
unit- единица измерения времени для аргументаtimeout - Возвращает:
-
trueесли все разрешения были получены иfalseесли время ожидания истекло до получения всех разрешений - Исключения:
-
InterruptedException- если текущий поток прерван -
IllegalArgumentException- еслиpermitsотрицательное
release
public void release(int permits)
Освобождает заданное количество разрешений, возвращая их семафору.
Освобождает заданное количество разрешений, увеличивая количество доступных разрешений на эту величину. Если какие-либо потоки пытаются получить разрешения, то выбирается один и ему предоставляются только что освобождённые разрешения. Если количество доступных разрешений удовлетворяет запросу этого потока, то этот поток (снова) активируется для планирования потоков; в противном случае поток будет ожидать, пока не станет доступно достаточное количество разрешений. Если после удовлетворения запроса этого потока всё ещё остаются разрешения, то эти разрешения по очереди назначаются другим потокам, пытающимся получить разрешения.
Нет требования, чтобы поток, который освобождает разрешение, должен был получить это разрешение вызовом acquire. Правильное использование семафора устанавливается соглашением программирования в приложении.
- Параметры:
-
permits- количество разрешений для освобождения - Исключения:
-
IllegalArgumentException- еслиpermitsотрицательное
availablePermits
public int availablePermits()
Возвращает текущее количество разрешений, доступных в этом семафоре.
Этот метод обычно используется для отладки и тестирования.
- Возвращает:
- количество разрешений, доступных в этом семафоре
drainPermits
public int drainPermits()
Получает и возвращает все разрешения, которые немедленно доступны.
- Возвращает:
- количество полученных разрешений
reducePermits
protected void reducePermits(int reduction)
Уменьшает количество доступных разрешений на указанное значение. Этот метод может быть полезен в подклассах, использующих семафоры для отслеживания ресурсов, которые становятся недоступными. Этот метод отличается от acquire тем, что не блокируется в ожидании, пока разрешения станут доступными.
- Параметры:
-
reduction- количество разрешений для удаления - Исключения:
-
IllegalArgumentException- еслиreductionотрицательное
isFair
public boolean isFair()
Возвращает true если для этого семафора установлена справедливость.
- Возвращает:
-
trueесли для этого семафора установлена справедливость
hasQueuedThreads
public final boolean hasQueuedThreads()
Опрашивает, ждут ли какие-либо потоки получения. Обратите внимание, что из-за возможных отмен в любое время возврат true не гарантирует, что какой-либо другой поток когда-либо получит. Этот метод предназначен в первую очередь для использования при мониторинге состояния системы.
- Возвращает:
-
trueесли могут быть другие потоки, ждущие получения
getQueueLength
public final int getQueueLength()
Возвращает оценку количества потоков, ожидающих получения. Значение является только оценкой, потому что количество потоков может динамически изменяться во время обхода внутренних структур данных. Этот метод предназначен для использования при мониторинге состояния системы, а не для управления синхронизацией.
- Возвращает:
- оцененное количество потоков, ожидающих этого замка
getQueuedThreads
protected Collection<Thread> getQueuedThreads()
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения. Поскольку фактический набор потоков может динамически меняться во время построения этого результата, возвращаемая коллекция является только оценкой с наилучшим усилием. Элементы возвращаемой коллекции не упорядочены по какому-либо определённому принципу. Этот метод предназначен для облегчения создания подклассов, которые обеспечивают более расширенные возможности мониторинга.
- Возвращает:
- коллекцию потоков
toString
public String toString()
Возвращает строку, идентифицирующую этот семафор, а также его состояние. Состояние, в скобках, включает строку "Permits =", за которой следует количество разрешений.
© 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.