Spec-Zone.ru › OpenJDK 25

Класс 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(), предшествуют по порядку выполнения действиям, следующим за успешным вызовом метода «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

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

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, 2025, Oracle и/или ее аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065, США.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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/Semaphore.html

Spec-Zone.ru

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