Win32 provides a mutex (which is a kernel object), along with a critical section, which is more
like a POSIX mutex. Win32 mutexes are recursive--meaning that the same thread can lock the
mutex multiple times. Java-synchronized sections are also recursive. We'll discuss this in more
We find it is somewhat confusing to use a generic term like critical section, which refers to a
concept, for the name of a specific synchronization variable.
In the nineteenth century, when trains were still advanced technology and railroad tracks were
exotic and expensive, it was common to run single sets of tracks and restrict the trains to travel in
only one direction at a time. Semaphores were invented to let the trains know if other trains were
on the rails at the same time. A semaphore was a vertical pole with a metal flag adjusted to hang at
either 45 or 90 degrees to indicate the existence of other trains.
In the 1960s, E. W. Dijkstra, a professor in the Department of Mathematics at the Technological
University, Eindhoven, Netherlands, extended this concept to computer science. A counting
semaphore (a.k.a. PV semaphore) is a variable that can increment arbitrarily high but decrement
only to zero. A POSIX sem_post() operation (a.k.a. "V"--verhogen in Dutch) increments the
semaphore, while a sem_wait() (a.k.a. "P"--proberen te verlagen) attempts to decrement it. If
the semaphore is greater than zero, the operation succeeds; if not, the calling thread must go to
sleep until a different thread increments it.
The word semaphore has come to take on other meanings in computer science. System V
semaphores, for example, are much more elaborate objects than counting semaphores.
A semaphore is useful for working with "trainlike" objects, that is, what you care about is whether
there are either zero objects or more than zero. Buffers and lists that fill and empty are good
examples. Semaphores are also useful when you want a thread to wait for something. You can
accomplish this by having the thread call sem_wait() on a semaphore with value zero, then
have another thread increment the semaphore when you're ready for the thread to continue (Code
Example 6-11 Basic Use of Counting Semaphores
In Figure 6-6 the semaphore started with a value of zero. The threads have executed their
respective operations in the order T1, T2, T3, T4, T5. After T1 executed its sem_wait(), it had
to wait (as the value was zero). When T2 did the sem_post(), T1 was awakened and
decremented the value back to zero. T3 did a sem_post(), incrementing the value to one. When
T4 did its sem_wait() it could continue without waiting at all. Finally, T5 called sem_wait(),
and is still waiting.
Figure 6-6. How a Semaphore Operates
Search WWH :