For example, a disastrous typo:
V(S)
critical section
V(S)
This leads to deadlock:
P(S)
critical section
P(S)
Nested critical sections can lead to deadlock:
P1 P2
-- --
P(Q) P(S)
P(S) P(Q)
... ...
V(S) V(Q)
V(Q) V(S)
Monitors are
Monitor, interface routines, condition variables, queues.

Two ``life simplifying'' assumptions regarding condition variables
Monitors can be implemented with semaphores:
semaphore mutex := 1
monitor operation 1 ....... monitor operation n
P(mutex) P(mutex)
... ...
V(mutex) V(mutex)
end end
Each condition variable cond_i has a COUNT_i
integer variable (initially 0) and a SEM_i
semaphore (initially 0) associated with it.
wait(cond_i):
COUNT_i++
V(mutex)
P(SEM_i)
P(mutex) <-----------------------delete---------
COUNT_i-- |
|-- problem
signal(cond_i): |
if COUNT_i > 0 then V(SEM_i) |
V(mutex) <-----------------------insert else----
exit the monitor
P(mutex)
and get in the monitor
before the signaled process can do its P(mutex)
P(mutex)
the condition may no longer be true
wait(cond_i):
COUNT_i++
V(mutex)
P(SEM_i)
COUNT_i--
signal(cond_i):
if COUNT_i > 0 then V(SEM_i)
else V(mutex)
exit the monitor
An SR resource that implements a collection of
ops/procs is not a monitor
because concurrent calls of the
ops/procs can be made.
A monitor condition variable is not the same as a semaphore because
V()'s are not lost if nobody queued on a P()
signal(cond_var) has no effect,
is not ``remembered'' if nobody is waiting
monitor.m.
The -sx argument means the signal and exit signaling
discipline.
m2sr -sx monitor.m
sr -o prog monitor.sr driver.sr
prog
In the bounded buffer monitor, _print(cv) prints the number
of processes in the wait queue on the condition variable cv;
the boolean function _empty(cv) will indicate if that queue
is empty or not.
The size of the buffer is gotten with getarg since SR monitors
cannot be parameterized like resources can (an SR monitor is like a global
resource in this regard).
Bounded Buffer Monitor.
Bounded Buffer SR Driver.
if count=1 then signal(not_empty) has been changed to just
signal(not_empty),
ditto if count=N-1 then signal(not_full)
We use an array of condition variables, one entry in the array per
philosopher.
A simple form of starvation prevention is used: a philosopher can become
``very hungry'' if it cannot eat when one of its neighbor's puts down
its forks.
A very hungry philosopher has priority to eat.
Notice that signal and wait, while easier to understand, does create
programming inconveniences.
Since putting down forks may involve generating two signals,
the philosopher finishing eating has to enter the monitor twice.
To leave the philospher code unchanged, a new resource
dining_interface in added to enter the monitor.
Starvation-Free Dining Philosophers Monitor.
Starvation-Free Dining Philosophers SR Driver.
A continual stream of arriving readers is not allowed to keep waiting
writers from entering the database.
Starvation-Free Readers and Writers Monitor.
Starvation-Free Readers and Writers SR Driver.
getarg to initialize some of their data.
This is not modular since all program parameters and data variables should
be initialized in one place.
The following program shows a general flexible technique that can be
used to initialize the data in a monitor using a global resource.
The Parameters global resource can be in a separate file,
or it can be in the same file as the monitor, preceding the monitor code,
as is the case in the sample compile and run shown.
In the latter case, the m2sr preprocessor will pass through
unchanged the global resource code preceding the monitor.
In fact, the driver can be in the monitor file, too, if the programming
conventions described in the ``man'' page for m2sr
are followed.
A note on two dimensional arrays of condition variables.
The usual subscripting expression [i,j] will not work
in _wait and _signal.
Use [i][j] instead, as shown in the program above.
dining_interface,
that made two calls to the monitor whenever a
philosopher put down its forks.
With signal and continue, only one call is needed, as shown below.
Since we can no longer guarantee that the condition that led to the signal
is still true when the signaled process proceeds in the monitor,
we need to take the precaution of changing the `if' statement containing
the wait,
if condition -> _wait(condvar) fito a `do while' loop,
do condition -> _wait(condvar) odWith multiple processes potentially being signaled before the signaler leaves the monitor, there is the possibility that the signal condition is no longer true when a particular waiting process wakes up. Further, some other process may have entered the monitor through an interface routine and modified the condition before the signaled process wakes up.
The -sc argument means the signal and continue signaling
discipline.
m2sr -sc monitor.m
sr -o prog monitor.sr driver.sr
prog
The sample output in the following SR program illustrates the differences
between the `signal and exit' and `signal and continue' signaling
disciplines.
Notice that m2sr -sx enforces that a process must exit
the monitor after sending a signal.
Also notice that m2sr -sc allows a process trying to get in
the monitor for the first time to enter before a signaled process can
continue inside the monitor.
Show Signaling Disciplines Monitor.
Show Signaling Disciplines Driver.
Here is the dining philosophers implemented with a `signal and continue'
monitor.
Dining Philosophers ``Signal and Continue'' Monitor.
Dining Philosophers ``Signal and Continue'' Driver.
This Java program shows that wait() and notify()
follow the ``signal and continue'' signaling discipline in a Java object
written as a monitor (synchronized methods).
Java Program: Show Monitor Signaling Discipline.
SJH shartley@mcs.drexel.edu