Monitors
A monitor is a higher-level form of synchronization than a semaphore or a lock. A monitor consists of data being synchronized, plus a lock, called the monitor lock, and one or more condition variables. Before it accesses the protected data, a thread first acquires the monitor lock. It is then said to be “in the monitor”. While in the monitor, the thread has control over all the protected data, which it may freely examine or modify. When access to the protected data is complete, it releases the monitor lock.
Condition variables allow code in the monitor to wait for a condition to become true. Each condition variable is associated with an abstract condition, e.g. “some data has arrived for processing” or “over 10 seconds has passed since the user’s last keystroke”. When code in the monitor needs to wait for a condition to become true, it “waits” on the associated condition variable, which releases the lock and waits for the condition to be signaled. If, on the other hand, it has caused one of these conditions to become true, it “signals” the condition to wake up one waiter, or “broadcasts” the condition to wake all of them.
The theoretical framework for monitors was laid out by C. A. R. Hoare. Their practical usage was later elaborated in a paper on the Mesa operating system.
Condition variable types and functions are declared in threads/synch.h
.
struct condition
Represents a condition variable.
void cond_init (struct condition *cond)
Initializes
cond
as a new condition variable.
void cond_wait (struct condition *cond, struct lock *lock)
Atomically releases
lock
(the monitor lock) and waits forcond
to be signaled by some other piece of code. Aftercond
is signaled, reacquireslock
before returning.lock
must be held before calling this function.
Sending a signal and waking up from a wait are not an atomic operation. Thus, typicallycond_wait
’s caller must recheck the condition after the wait completes and, if necessary, wait again.
void cond_signal (struct condition *cond, struct lock *lock)
If any threads are waiting on
cond
(protected by monitor locklock
), then this function wakes up one of them. If no threads are waiting, returns without performing any action.lock
must be held before calling this function.
void cond_broadcast (struct condition *cond, struct lock *lock)
Wakes up all threads, if any, waiting on
cond
(protected by monitor locklock
).lock
must be held before calling this function.