Synchronization Patterns • Counting SemaphoresMedium⏱️ ~2 min
Semaphore Operations: Wait and Signal Semantics
Core Operations
Semaphores have two atomic operations: wait() (also called P, down, acquire) and signal() (also called V, up, release).
Wait Operation (P, Down, Acquire)
Atomically: if value > 0, decrement and return. If value <= 0, block until signaled, then decrement and return. A thread that waits either proceeds immediately or blocks.
Signal Operation (V, Up, Release)
Atomically: increment value. If any threads are blocked, wake one of them. Signal never blocks. It always completes immediately.
Alternative Names (Same Operations)
Why P and V?
Dijkstra used Dutch words: P for "proberen" (to try) and V for "verhogen" (to increase). Historical artifact. Most modern APIs use wait/signal or acquire/release.
Atomicity Matters
Both operations are atomic - they happen as a single, uninterruptible unit. A thread cannot be interrupted between checking the value and decrementing it. This is what makes semaphores safe for synchronization.
Key Properties: wait() may block, signal() never blocks. Both are atomic. Signal wakes at most one waiter. Multiple waiters queue up and are woken one at a time.
💡 Key Takeaways
✓wait() (P, down, acquire): decrement, block if result would be negative. May block the caller.
✓signal() (V, up, release): increment, wake one waiter if any. Never blocks.
✓P and V are Dutch abbreviations from Dijkstra. Modern APIs use wait/signal or acquire/release.
✓Both operations are atomic. Check-and-modify happens as one uninterruptible action.
✓Multiple blocked threads form a queue. Each signal() wakes exactly one (FIFO or unspecified order).
📌 Examples
1Java Semaphore: acquire() and release(). Also tryAcquire() for non-blocking attempt.
2POSIX sem_t: sem_wait() and sem_post(). sem_trywait() for non-blocking.
3Python threading.Semaphore: acquire() and release(). acquire(blocking=False) for try-acquire.