Synchronization PatternsCounting SemaphoresMedium⏱️ ~2 min

The Semaphore Value: What It Really Means

Key Insight
The semaphore value has different meanings when positive vs negative. Understanding this is crucial for debugging.

Positive Value: Available Permits

When the value is positive (say, 3), it means 3 more threads can call wait() and proceed immediately without blocking. These are available permits waiting to be claimed.

Zero Value: Fully Occupied

When the value is 0, all permits are taken. No threads are waiting yet, but the next thread to call wait() will block. The resource pool is exactly at capacity.

Negative Value: Waiting Queue

When the value is negative (say, -2), it means 2 threads are blocked, waiting in queue. All permits are taken AND there is a backlog. The absolute value tells you the queue length.

Semaphore Value Interpretation (N=3)
value = 21 thread inside2 permits free0 waitingvalue = 03 threads inside0 permits free0 waitingvalue = -23 threads inside0 permits free2 waiting

You Cannot Read the Value

In most implementations, you cannot directly check the semaphore value. This is by design - the value could change between reading and acting on it. You can only wait() and signal().

Debugging tip: Some implementations offer a tryWait() that returns immediately (success or failure) without blocking. Useful for testing but not for production logic.

Mental Model: Positive = permits available. Zero = at capacity. Negative = queue depth. The semaphore is an integer that threads can only modify atomically, never read.
💡 Key Takeaways
Positive value: that many threads can call wait() without blocking. Available permits.
Zero value: all permits taken, no queue yet. Next wait() will block.
Negative value: absolute value is the number of threads blocked in the waiting queue.
Cannot read the value directly in most APIs. Value could change between read and action.
signal() increments and wakes one waiter (if any). wait() decrements and blocks (if would go negative).
📌 Examples
1Semaphore(5) after 3 waits: value is 2. Two more threads can proceed immediately.
2Semaphore(5) after 5 waits: value is 0. Pool is full. Next wait blocks.
3Semaphore(5) after 7 waits: value is -2. Pool full AND 2 threads waiting in queue.
← Back to Counting Semaphores Overview