What is a counting semaphore and when would you use one?
A counting semaphore holds a non-negative integer that tracks how many units of a resource are free. wait() takes one unit (blocking at zero) and signal() returns one. It limits how many threads use a pool at once.
Explain it simply
Think of a parking lot with 3 free slots and a board showing the number. A car entering decrements the board; if it reads 0, the car waits at the gate. A car leaving increments it and lets one waiting car in.
A counting semaphore is that board. Its value can be any non-negative integer, unlike a binary semaphore, which is only 0 or 1.
wait()(also called P or down): if value > 0, subtract 1 and go on; otherwise block.signal()(also called V or up): add 1 and wake one blocked process, if any.
Both operations are atomic.
Example
A server allows at most 3 database connections at once:
semaphore pool = 3
worker():
wait(pool) // value 3 -> 2 -> 1 -> 0, the fourth worker blocks
use_connection()
signal(pool) // value goes back up, one blocked worker wakesTrace with 5 workers arriving together: W1, W2, W3 pass (value 0). W4 and W5 block. When W1 signals, the value becomes 1 and W4 wakes, taking it back to 0. W5 stays blocked until another worker signals.
At no moment are more than 3 workers inside the guarded section.
What to say in the interview
"A counting semaphore stores the number of available resource units. wait decrements and blocks at zero; signal increments and wakes a waiter. I'd use one to limit access to a pool, such as 3 DB connections or N buffer slots."
Common mistakes
- Calling wait() and then forgetting signal() on an error path, which leaks a unit permanently.