4.2.5. The MonitorΒΆ

The semaphore provides a foundation for implementing solutions to synchronization problems. Unfortunately, finding a completely correct solution to some of the more challenging problems using semaphores is quit difficult. Thus, many programming environments use semaphores, or the same facilities used to implement semaphores, to provide an alternative called monitors, which for some problems allows for a simpler solution. Monitors are also often called conditional waits or conditional monitors.

The conditional monitor object contains an internal mutual exclusion lock and methods for a process to wait() until another thread issues a notify() method to awake the thread. Correct use of monitors is fairly simple, but generally calls for following a fixed programing model. See Python’s Conditional Monitor and Classic Synchronization Problems for examples. The key to correctly using a monitor is to always put the wait() operation inside a while loop as shown below. The monitor’s wait() method releases the held lock so that other threads are not held up, but reacquires it when exiting the waiting state. Thus, the check to enter the critical state (the negative of the while loop boolean expression), is always done with mutual exclusion. The monitor allows the programmer to simply express the criteria for entering the critical section in terms of a boolean expression, which generally simplifies the solution to many problems.

/* Code to enter a critical section */
monitor.acquire();
while( not_okay_to_enter() )
    monitor.wait();
keep_others_out();
monitor.release();
/*---------------------------------*/
/*    Critical Section             */
/*---------------------------------*/
/* Exit of critical section code   */
monitor.acquire();
okay_others_to_enter();
monitor.notify();
monitor.release();

Here is the implementation of a monitor using a semaphore in pseudo code.

Abstract Data Type condition is
   count   : integer initialized to 0;
   queue   : semaphore initialized to 0 (i.e. blocking);

procedure wait (x : in out condition) is
begin
    x.count++;
    if next_count > 0 then V(next) else V(mutex);
    P(x.queue);
    P(next);
    next_count--;
end;

procedure signal (x : in out condition) is
begin
    if x.count > 0 then
    begin
        x.count--;
        next_count++;
        V(x.queue);
    end;
end;