Spec-Zone.ru › OpenJDK 27

Класс Semaphore

java.lang.Object
java.util.concurrent.Semaphore
Все реализуемые интерфейсы:
Serializable
public class Semaphore extends Object implements Serializable
Семафор со счетчиком. Концептуально семафор хранит набор разрешений. Каждый вызов acquire() при необходимости блокируется, пока не появится доступное разрешение, а затем получает его. Каждый вызов release() добавляет разрешение, потенциально освобождая ожидающий поток, пытающийся получить разрешение. Однако фактические объекты разрешений не используются; Semaphore лишь ведет счетчик доступных разрешений и действует соответствующим образом.

Семафоры часто используются для ограничения числа потоков, которые могут обращаться к некоторому (физическому или логическому) ресурсу. Например, ниже приведен класс, который использует семафор для управления доступом к пулу элементов:

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 нескольких разрешений за один раз. Как правило, эти методы эффективнее и удобнее циклов. Однако они не устанавливают никакого предпочтительного порядка. Например, если поток A вызывает s.acquire(3), а поток B вызывает s.acquire(2), и становятся доступны два разрешения, нет гарантии, что поток B получит их, если только он не начал выполнение acquire первым и Semaphore s не работает в справедливом режиме.

Эффекты согласованности памяти: действия в потоке, предшествующие вызову метода «release», например release() happen-before действий, следующих за успешным вызовом метода «acquire», например acquire(), в другом потоке.

Начиная с версии:
1.5
См. также:
  • Сериализованная форма

Краткое описание конструкторов

Конструктор Описание
Semaphore(int permits)
Создает Semaphore с указанным числом разрешений и настройкой несправедливого порядка.
Semaphore(int permits, boolean fair)
Создает Semaphore с указанным числом разрешений и заданной настройкой справедливости.

Краткое описание методов

Модификатор и тип Метод Описание
void acquire()
Получает разрешение от этого семафора, блокируясь до тех пор, пока оно не станет доступно или поток не будет прерван.
void acquire(int permits)
Получает указанное число разрешений от этого семафора, блокируясь до тех пор, пока все они не станут доступны или поток не будет прерван.
void acquireUninterruptibly()
Получает разрешение от этого семафора, блокируясь до тех пор, пока оно не станет доступно.
void acquireUninterruptibly(int permits)
Получает указанное число разрешений от этого семафора, блокируясь до тех пор, пока все они не станут доступны.
int availablePermits()
Возвращает текущее число разрешений, доступных в этом семафоре.
int drainPermits()
Получает и возвращает все немедленно доступные разрешения или, если число разрешений отрицательно, освобождает их.
protected Collection<Thread> getQueuedThreads()
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения разрешения.
final int getQueueLength()
Возвращает оценочное число потоков, ожидающих получения разрешения.
final boolean hasQueuedThreads()
Проверяет, ожидают ли какие-либо потоки получения разрешения.
boolean isFair()
Возвращает true, если для этого семафора включен справедливый порядок.
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)
Получает разрешение от этого семафора, если оно станет доступно в течение заданного времени ожидания и текущий поток не будет прерван.

Методы, объявленные в классе Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Модификатор и тип Метод Описание
protected Object clone()
Создает и возвращает копию этого объекта.
boolean equals(Object obj)
Указывает, равен ли этот объект другому объекту.
protected void finalize()
Устарело, будет удалено: этот элемент API подлежит удалению в будущей версии.
Финализация объявлена устаревшей и подлежит удалению в одном из будущих выпусков.
final Class<?> getClass()
Возвращает класс времени выполнения этого Object.
int hashCode()
Возвращает хеш-код этого объекта.
final void notify()
Пробуждает один поток, ожидающий на мониторе этого объекта.
final void notifyAll()
Пробуждает все потоки, ожидающие на мониторе этого объекта.
final void wait()
Заставляет текущий поток ожидать пробуждения, обычно вследствие вызова notify или interrupt.
final void wait(long timeoutMillis)
Заставляет текущий поток ожидать пробуждения, обычно вследствие вызова notify или interrupt, либо до истечения определенного промежутка реального времени.
final void wait(long timeoutMillis, int nanos)
Заставляет текущий поток ожидать пробуждения, обычно вследствие вызова notify или interrupt, либо до истечения определенного промежутка реального времени.

Подробное описание конструкторов

Semaphore

public Semaphore(int permits)
Создает Semaphore с указанным количеством разрешений и без настройки справедливого порядка.
Параметры:
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
Получает указанное количество разрешений от этого семафора, блокируя выполнение до тех пор, пока все они не станут доступны или поток не будет прерван.

Получает указанное количество разрешений, если они доступны, и немедленно возвращает управление, уменьшая количество доступных разрешений на указанную величину. Этот метод эквивалентен циклу for (int i = 0; i < permits; ++i) acquire();, за исключением того, что он атомарно получает все разрешения одновременно:

Если доступно недостаточно разрешений, текущий поток исключается из планирования потоков и ожидает, пока не произойдет одно из двух событий:

  • Какой-либо другой поток вызывает один из методов release для этого семафора, текущему потоку следующим назначаются разрешения, и количество доступных разрешений удовлетворяет этому запросу; или
  • Какой-либо другой поток прерывает текущий поток.

Если текущий поток:

  • при входе в этот метод имеет установленный статус прерывания; или
  • будучи в ожидании разрешения, прерывается,
выбрасывается InterruptedException, а статус прерывания текущего потока сбрасывается. Любые разрешения, которые должны были быть назначены этому потоку, вместо этого назначаются другим потокам, пытающимся получить разрешения, как если бы разрешения стали доступны в результате вызова release().
Параметры:
permits — количество разрешений для получения
Выбрасывает:
InterruptedException — если текущий поток прерван
IllegalArgumentException — если permits отрицательно

acquireUninterruptibly

public void acquireUninterruptibly(int permits)
Получает указанное количество разрешений от этого семафора, блокируя выполнение до тех пор, пока все они не станут доступны.

Получает указанное количество разрешений, если они доступны, и немедленно возвращает управление, уменьшая количество доступных разрешений на указанную величину. Этот метод эквивалентен циклу for (int i = 0; i < permits; ++i) acquireUninterruptibly();, за исключением того, что он атомарно получает все разрешения одновременно:

Если доступно недостаточно разрешений, текущий поток исключается из планирования потоков и ожидает, пока какой-либо другой поток не вызовет один из методов 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 =", за которой следует количество разрешений.
Переопределяет:
toString в классе Object
Возвращает:
строку, идентифицирующую этот семафор и его состояние

Сообщить об ошибке или предложить улучшение
Дополнительную справочную информацию по API и документацию для разработчиков см. в разделе Документация Java SE, содержащем более подробные описания для разработчиков, обзоры концепций, определения терминов, обходные решения и работающие примеры кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или ее аффилированных лиц в США и других странах.
Авторское право © 1993, 2026, Oracle и/или ее аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API