# Semaphore A **semaphore** is a counter, manipulated only through two atomic operations traditionally called `wait` (or `P`, `acquire`) and `signal` (or `V`, `release`). `wait` decrements the counter and blocks the calling thread if the result would go negative; `signal` increments the counter and wakes a waiting thread if one is blocked. Edsger Dijkstra introduced the concept in 1965 as a general tool for both mutual exclusion and coordination. ```c #include sem_t sem; sem_init(&sem, 0, 3); // initial count of 3: up to 3 concurrent holders void use_resource(void) { sem_wait(&sem); // acquire: blocks if count is already 0 /* ... use one of 3 available resource slots ... */ sem_post(&sem); // release: increments count, wakes a waiter if any } ``` ## Counting vs binary A **counting semaphore** initialized to N allows up to N threads to pass `wait` before any of them blocks, making it a natural fit for limiting concurrent access to a pool of N identical resources (database connections, worker slots). A **binary semaphore** is the special case initialized to 1, which looks like a [[sync-mutex|mutex]] on the surface but is not the same thing. ## Why it isn't a mutex A semaphore has no concept of ownership: any thread can call `signal`, not just the thread that called `wait`. This makes a binary semaphore usable for a pattern a mutex cannot express directly, thread A waits for a signal that thread B sends, since a mutex assumes whoever locked it will be the one to unlock it. The cost of that flexibility is that a semaphore can't protect you from a bug where the wrong thread releases it; a mutex's ownership check exists specifically to catch that class of mistake.