Семафор – один из старейших примитивов синхронизации. Он был изобретен Дейкстрой в 1968 году. По большому счету это счетчик, который можно увеличивать и уменьшать из разных потоков. Уменьшение до 0 блокирует уменьшающий поток. Состояние, когда счетчик больше нуля называют
сигнальное состояние, операцию его увеличения –
release (освобождение) или
signal, уменьшения –
acquire (захват) или
wait.
На практике можно представить, что release – выделение квоты доступа к критической секции программы. acquire – использование необходимого объема доступной квоты, или ожидание, если её не хватает. Подробнее с деталями работы семафора поможет ознакомиться
перевод статьи с картинками на хабре.
В Java семафор реализован классом
Semaphore. Состоит этот класс в основном из разных форм методов
acquire (с таймаутом, с игнорированием
InterruptedException, неблокирующий) и
release. Методы могут принимать параметр
permits – тот самый объем квот, которые необходимо освободить/захватить.
Несколько вспомогательных методов позволяют узнать больше о количестве и составе очереди потоков, которые ждут освобождения пермитов. А методы
availablePermits и
drainPermits позволяют узнать количество оставшихся пермитов, и захватить их все соответственно. В конструкторе конфигурируются изначальное количество пермитов, и свойство
fair (аналогичное свойству
ReentrantLock).