Semaphores, another important contribution by E. W. Dijkstra,
can be viewed as an extension to mutex locks. A semaphore is an object
with two methods Wait and Signal, a private integer counter and a
private queue (of threads). The semantics of a semaphore is very simple.
Suppose S is a semaphore whose private counter has been
initialized to a non-negative integer.
The operations of Wait or Signal are
atomic. This means once the
activities of Wait start (i.e., testing and decreasing the value
of the counter and putting the thread into the queue), they will continue
to the end without
any interruption. More precisely, even though there are many steps to
carry out Wait and Signal, these steps are considered as
a single non-interruptible instruction. Similarly, the same applies to
Signal. Moreover, if more than one threads try to execute Wait (or
Signal), only one of them will succeed.
We should not make any assumption about which thread
will succeed.