Класс Semaphore
Класс Semaphore представляет собой семафор -
примитив синхронизации, который управляет доступом
к общему ресурсу с помощью счетчика разрешений.
Семафор хранит некоторое количество разрешений.
Поток, желающий получить доступ к ресурсу, вызывает
метод acquire, который уменьшает счетчик
разрешений на единицу. Если счетчик равен нулю,
поток блокируется до тех пор, пока другой поток
не освободит разрешение через метод release.
В конструктор семафора мы передаем начальное
количество разрешений. Вторым параметром можно
передать флаг fair, который определяет
порядок предоставления разрешений ожидающим потокам.
Синтаксис
Semaphore semaphore = new Semaphore(permits);
Semaphore semaphore = new Semaphore(permits, fair);
Основные методы
Класс Semaphore предоставляет следующие
основные методы:
acquire - уменьшает счетчик разрешений
на единицу, блокируя поток, если разрешений нет.
release - увеличивает счетчик разрешений
на единицу, освобождая ресурс.
tryAcquire - пытается получить разрешение
без блокировки, возвращает true или
false.
availablePermits - возвращает текущее
количество доступных разрешений.
Пример
Давайте создадим семафор с двумя разрешениями и запустим четыре потока, которые будут получать доступ к ресурсу:
import java.util.concurrent.Semaphore;
public class Main
{
public static void main(String[] args)
{
Semaphore semaphore = new Semaphore(2);
for (int i = 1; i <= 4; i++)
{
final int id = i;
new Thread(() -> {
try
{
semaphore.acquire();
System.out.println("Thread " + id + " acquired");
Thread.sleep(100);
System.out.println("Thread " + id + " released");
semaphore.release();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}).start();
}
}
}
Результат выполнения кода:
"Thread 1 acquired"
"Thread 2 acquired"
"Thread 1 released"
"Thread 3 acquired"
"Thread 2 released"
"Thread 4 acquired"
"Thread 3 released"
"Thread 4 released"
Пример
Давайте проверим количество доступных разрешений
с помощью метода availablePermits:
import java.util.concurrent.Semaphore;
public class Main
{
public static void main(String[] args)
{
Semaphore semaphore = new Semaphore(3);
System.out.println(semaphore.availablePermits());
try
{
semaphore.acquire();
System.out.println(semaphore.availablePermits());
semaphore.acquire();
System.out.println(semaphore.availablePermits());
semaphore.release();
System.out.println(semaphore.availablePermits());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
Результат выполнения кода:
3
2
1
2
Пример
Давайте используем метод tryAcquire
для неблокирующей попытки получения разрешения:
import java.util.concurrent.Semaphore;
public class Main
{
public static void main(String[] args)
{
Semaphore semaphore = new Semaphore(1);
boolean res1 = semaphore.tryAcquire();
System.out.println(res1);
boolean res2 = semaphore.tryAcquire();
System.out.println(res2);
semaphore.release();
boolean res3 = semaphore.tryAcquire();
System.out.println(res3);
}
}
Результат выполнения кода:
true
false
true
Смотрите также
-
метод
acquire,
который получает разрешение у семафора -
метод
release,
который освобождает разрешение семафора -
метод
tryAcquire,
который пытается получить разрешение без блокировки -
класс
ReentrantLock,
который представляет повторно входимую блокировку