The three topics covered on January 21 were
Condition synchronization is a more complex form of synchronization than simple mutual exclusion. The goal of condition synchronization is to associate conditions on the state of the system with certain operations, so that those operations are performed only when the system is in some acceptable state. For example, in the producer-consumer problem we only want producers to produce when the buffer is not full. In that case, the operation is producing, and the condition we want to associate with that operation is "buffer not full."
Another requirement of condition synchronization that the state of the system doesn't change while conditions are being evaluated. If it did, there could obviously be all kinds of consistency problems.
SUMMARY OF REQUIREMENTS
The monitor model (developed by Tony Hoare) is a way of achieving the requirements of condition synchronization. The key parts of the model are
All shared resources must be accessed through the procedures/methods provided by the monitor object. The state variables store the current state of the system. The condition variables are used to keep track of which processes/threads are waiting on which conditions. The way that these parts of the model work together is as follows.
In order to access a shared resource (or perform some other potentially-dangerous operation), a thread must call one of the monitor methods. Because of the mutual-exclusion lock, only one process is allowed to execute a monitor method at a time. Once the thread enters the monitor, the state variables are used to test the condition(s) that must be true for the thread to proceed. If the condition is true, the thread is allowed to continue and the state variables are updated as necessary. If the condition is false, however, the wait() method of the associated condition variable is called, causing the thread to to placed on the condition variable's queue. Later, when subsequent operations by other threads make the condition true, the signal() method of the condition variable is called to wake up the thread (or threads) that were waiting for that condition.
There are some possible variations in the exact semantics of the signal() operation.
Monitors can be implemented using the Java programming language. The three key parts of the model are implemented as follows.
The following example shows a bounded counter implemented using both Hoare-style pseudocode and Java code. Comments on the example are given below.
// HOARE'S MONITOR MODEL // MONITOR IMPLEMENTED IN JAVA
monitor BoundedCounterVST class BoundedCounterVST extends Object
begin {
condition belowMax, aboveMin; // One implicit condition variable
integer value; private int value;
constant MAX=100, MIN=0; final int MAX=100, MIN=0;
integer value() public synchronized int value()
begin {
return value; return value;
end }
void inc() public synchronized void inc()
begin {
if (value == MAX) while (value == MAX)
belowMax.wait(); try {wait();} catch(Exception e) {}
value = value + 1; value += 1;
if (value == MIN+1) if (value == MIN+1)
aboveMin.signal(); notifyAll();
end }
void dec() public synchronized void dec()
begin {
if (value == MIN) while (value == MIN)
aboveMin.wait(); try {wait();} catch(Exception e) {}
value = value - 1; value -= 1;
if (value == MAX-1) if (value == MAX-1)
belowMax.signal(); notifyAll();
end }
begin BoundedCounterVST() {
value = MIN; value = MIN;
end }
end }
Notice that condition variables are not declared in the Java code, since there is no explicit condition variable type (although we could write our own). This means that there is no way in Java to specify or determine which condition a particular thread is waiting for if there is more than one condition tested by the monitor. Most of the other differences in the code can be attributed to this limitation.