OS Concepts · Chapter 6
A counting semaphore generalizes the lock to N interchangeable instances of a resource, with a wait queue instead of busy-waiting.
wait(S) decrements S; if S goes negative the caller blocks and joins S's waiting list (no spinning). signal(S) increments S and, if anyone was waiting, wakes one of them.