Ответ
Semaphore (Семафор) — это механизм синхронизации из пакета java.util.concurrent, который ограничивает количество потоков, которые могут одновременно получить доступ к общему ресурсу или пулу ресурсов. Он управляет набором виртуальных разрешений (permits).
Основные операции:
acquire()— Запрашивает одно разрешение. Если разрешения доступны, счетчик уменьшается, и поток продолжает работу. Если нет — поток блокируется до освобождения разрешения.release()— Освобождает одно разрешение, увеличивая счетчик и потенциально разблокируя ожидающий поток.
Пример: Ограничение доступа к пулу из 3-х соединений.
import java.util.concurrent.Semaphore;
public class ConnectionPool {
private final Semaphore semaphore = new Semaphore(3); // Макс. 3 потока одновременно
public void useResource() {
try {
semaphore.acquire(); // Получаем разрешение
// Критическая секция: работа с ограниченным ресурсом (например, сетевое соединение)
System.out.println(Thread.currentThread().getName() + " начал работу. Свободно разрешений: " + semaphore.availablePermits());
Thread.sleep(1000); // Имитация работы
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release(); // Всегда освобождаем разрешение в finally!
System.out.println(Thread.currentThread().getName() + " закончил работу.");
}
}
}
// Запуск 10 потоков, но одновременно работают не более 3-х.
Важные особенности:
- Честность (Fairness): Конструктор
Semaphore(int permits, boolean fair). Приfair=trueразрешения предоставляются ожидающим потокам в порядке FIFO, что предотвращает голодание, но может снижать производительность. - Множественное приобретение/освобождение: Методы
acquire(int permits)иrelease(int permits)работают с несколькими разрешениями сразу. - Попытка без блокировки:
tryAcquire()возвращаетfalseнемедленно, если разрешение недоступно.
Типичные сценарии использования:
- Ограничение числа одновременных соединений к базе данных или внешнему API.
- Реализация пулов ресурсов (например, потоков, соединений).
- Создание ограниченных по пропускной способности шлюзов (rate limiting).
Отличие от ReentrantLock: Семафор не привязан к конкретному потоку. Разрешение, полученное одним потоком, может быть освобождено другим (хотя это не является хорошей практикой).