In multithreaded programming, it’s important to make threads wait. They must wait for exclusive access to a resource. They must wait when there’s no work available. One way to make threads wait – and put them to sleep inside the kernel, so that they no longer take any CPU time – is with a semaphore.
I used to think semaphores were strange and old-fashioned. They were invented by Edsger Dijkstra back in the early 1960s, before anyone had done much multithreaded programming, or much programming at all, for that matter. I knew that a semaphore could keep track of available units of a resource, or function as a clunky kind of mutex, but that seemed to be about it.
My opinion changed once I realized that, using only semaphores and atomic operations, it’s possible to implement all of the following primitives:
- A Lightweight Mutex
- A Lightweight Auto-Reset Event Object
- A Lightweight Read-Write Lock
- Another Solution to the Dining Philosophers Problem
- A Lightweight Semaphore With Partial Spinning