Spec-Zone.ru › OpenJDK 21

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

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

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

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

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

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

Сеmaphore

public Semaphore(int permits)
Создаёт Semaphore с заданным числом разрешений и значением нечестной политики справедливости.
Параметры:
permits - начальное число доступных разрешений. Это значение может быть отрицательным, в этом случае вызовы release() должны произойти перед любыми вызовами acquire() .

Сеmaphore

public Semaphore(int permits, boolean fair)
Создаёт Semaphore с заданным числом разрешений и заданной политикой справедливости.
Параметры:
permits - начальное число доступных разрешений. Это значение может быть отрицательным, в этом случае вызовы release() должны произойти перед любыми вызовами acquire() .
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), которое почти эквивалентно (также обнаруживает прерывание).

Parameters:
permits - количество разрешений для получения
Returns:
true если разрешения были получены и false в противном случае
Throws:
IllegalArgumentException - если permits отрицательно

tryAcquire

public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
Получает заданное количество разрешений из этого семафора, если все они становятся доступными в течение заданного времени ожидания, и текущий поток не был прерван.

Получает заданное количество разрешений, если они доступны и возвращает немедленно, со значением true, уменьшая количество доступных разрешений на указанную сумму.

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

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

Если разрешения получены, возвращается значение true.

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

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

Если заданное время ожидания истекает, возвращается значение false. Если время меньше или равно нулю, метод вообще не будет ожидать. Любые разрешения, которые должны были быть назначены этому потоку, вместо этого назначаются другим потокам, пытающимся получить разрешения, как если бы разрешения были сделаны доступными вызовом release().

Parameters:
permits - количество разрешений для получения
timeout - максимальное время ожидания разрешений
unit - единица измерения времени для аргумента timeout
Returns:
true если все разрешения были получены и false если время ожидания истекло до получения всех разрешений
Throws:
InterruptedException - если текущий поток прерван
IllegalArgumentException - если permits отрицательно

release

public void release(int permits)
Освобождает заданное количество разрешений, возвращая их семафору.

Освобождает заданное количество разрешений, увеличивая количество доступных разрешений на эту сумму. Если какие-либо потоки пытаются получить разрешения, то выбирается один поток и получает разрешения, которые только что были освобождены. Если количество доступных разрешений удовлетворяет запросу этого потока, то этот поток (снова) активируется для целей планирования потоков; в противном случае поток будет ожидать, пока не будет достаточно разрешений. Если после удовлетворения запроса этого потока все еще есть доступные разрешения, эти разрешения по очереди назначаются другим потокам, пытающимся получить разрешения.

Нет требования, чтобы поток, который освобождает разрешение, должен был получить это разрешение, вызвав acquire. Правильное использование семафора определяется соглашениями по программированию в приложении.

Parameters:
permits - количество разрешений для освобождения
Throws:
IllegalArgumentException - если permits отрицательно

availablePermits

public int availablePermits()
Возвращает текущее количество доступных разрешений в этом семафоре.

Этот метод обычно используется для отладки и тестирования.

Returns:
количество доступных разрешений в этом семафоре

drainPermits

public int drainPermits()
Получает и возвращает все сразу доступные разрешения или, если доступны отрицательные разрешения, освобождает их. По возвращении разрешений нет.
Returns:
количество полученных разрешений, или, если отрицательно, количество освобожденных разрешений

reducePermits

protected void reducePermits(int reduction)
Уменьшает количество доступных разрешений на указанное значение. Этот метод может быть полезен в подклассах, которые используют семафоры для отслеживания ресурсов, которые становятся недоступными. Этот метод отличается от acquire тем, что не блокирует ожидание, пока разрешения не станут доступными.
Parameters:
reduction - количество разрешений для удаления
Throws:
IllegalArgumentException - если reduction отрицательно

isFair

public boolean isFair()
Возвращает true если для этого семафора установлена справедливость.
Returns:
true если для этого семафора установлена справедливость

hasQueuedThreads

public final boolean hasQueuedThreads()
Определяет, ждут ли какие-либо потоки получения. Обратите внимание, что из-за возможных отмен в любое время возвращаемое значение true не гарантирует, что какой-либо другой поток когда-либо получит разрешение. Этот метод предназначен в основном для мониторинга состояния системы.
Returns:
true если могут быть другие потоки, ожидающие получения

getQueueLength

public final int getQueueLength()
Возвращает оценку количества потоков, ожидающих получения. Значение является только оценкой, потому что количество потоков может динамически меняться во время обхода внутренних структур данных. Этот метод предназначен для использования в мониторинге состояния системы, а не для управления синхронизацией.
Returns:
приблизительное количество потоков, ожидающих этого блокирования

getQueuedThreads

protected Collection<Thread> getQueuedThreads()
Возвращает коллекцию, содержащую потоки, которые могут ожидать получения. Поскольку фактический набор потоков может динамически изменяться во время построения этого результата, возвращаемая коллекция является лишь приблизительной оценкой. Элементы возвращаемой коллекции не упорядочены. Этот метод предназначен для упрощения создания подклассов, обеспечивающих более обширные возможности мониторинга.
Returns:
коллекция потоков

toString

public String toString()
Возвращает строку, идентифицирующую этот семафор, а также его состояние. Состояние, в квадратных скобках, включает строку "Permits =" и количество разрешений.
Overrides:
toString in class Object
Returns:
строка, идентифицирующая этот семафор и его состояние

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

Spec-Zone.ru

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