A semaphore is a synchronisation primitive used to control access to shared resources in concurrent programs by maintaining an integer count that represents the number of available permits. Two atomic operations define a semaphore: wait (P, decrement — block if zero) and signal (V, increment — wake a waiting thread). Introduced by Edsger Dijkstra in 1965, semaphores prevent race conditions and are foundational to operating system design, used for mutual exclusion (binary semaphore / mutex) and resource pool management (counting semaphore).
| Property | Binary Semaphore | Counting Semaphore | Mutex |
|---|---|---|---|
| Initial value | 0 or 1 | 0 to N | 1 (unlocked) |
| Max value | 1 | N (resource count) | 1 |
| Ownership | None | None | Owning thread only |
| Use case | Signalling between threads | Limiting pool access | Mutual exclusion |
| Release by non-owner? | Yes | Yes | No (undefined / error) |
Wikimedia Commons, CC BY-SA
Concurrency is the ability of a program to manage multiple tasks that are in progress at the same time, potentially interleaving their execution on one or more processors. Unlike parallelism (simultaneous execution on multiple cores), concurrency is about program structure — decomposing a problem into independently progressing tasks that communicate and coordinate. Concurrency is essential for responsive UIs, servers handling multiple clients, and efficient use of modern multi-core hardware, and is expressed through threads, coroutines, async/await, and actor models.
A thread is the smallest unit of execution within a process, representing an independent sequence of instructions that can be scheduled by the operating system. Multiple threads within a single process share the same memory space (heap, global variables) but each maintains its own stack, program counter, and register state. Threads enable concurrency and parallelism within applications, and are central to modern programming in systems languages (C++, Java, Go) as well as high-level frameworks.
From Greek "sema" (sign) + "phoros" (bearer). Edsger Dijkstra coined the computing term in his 1965 paper "Cooperating Sequential Processes", borrowing from railway semaphore signals that control train access to shared tracks.