Semaphore
Control access to a finite pool of resources by maintaining a counter that threads atomically increment (release) and decrement (acquire), blocking when the count reaches zero.
errorWhat Problem Does the Semaphore Pattern Solve?
A mutex permits exactly one thread into a critical section, but many resources exist in limited quantities greater than one — a database connection pool of ten, a rate limit of five concurrent API calls, or three available GPU slots. Using one mutex per resource instance is unwieldy and doesn't naturally express the pool abstraction.
check_circleHow the Semaphore Pattern Works
Initialise a semaphore with a count equal to the number of available resource units. Each acquire decrements the count; if it would go below zero, the calling thread blocks. Each release increments the count, waking a blocked thread if any are waiting. This elegantly generalises the mutex (a semaphore initialised to 1) to arbitrary resource counts.
Semaphore Pattern Architecture
Rendering diagram...
Implementation by Language
Semaphore Pattern in the Real World
“Imagine a car park with exactly three spaces. A ticket machine at the entrance (the semaphore) issues a ticket only if spaces remain, lifting the barrier; arriving drivers with no ticket available must wait. When a car exits, the machine automatically increments its counter and releases the next waiting driver — the car park never exceeds capacity.”
Frequently Asked Questions
helpWhen should I use a Semaphore instead of a rate limiter?
Use a Semaphore to limit concurrent access (max N operations running simultaneously). Use a rate limiter to limit throughput over time (max N operations per second). A Semaphore doesn't care about time — it controls how many operations run at once, not how fast they start.
helpWhat happens if a Semaphore is never released?
The semaphore's count is permanently decremented, reducing the available permits. If all permits are leaked, the semaphore deadlocks — no new operations can acquire a permit. Always release in a finally block (try/finally) to prevent leaks, even when exceptions occur.