C++ / a working model

163 / 163   ·   C11   ·   8 min

Monitors

Keep this sentence

This appendix presents monitors as a construct that packages shared data with its access operations into one module while automatically supplying mutual exclusion, uses condition variables for wait-and-signal, and contrasts Hoare versus Mesa semantics as they appear in real implementations.

In this lesson
  1. How a Monitor Automatically Guarantees Mutual Exclusion
  2. Condition Variables Must Be Paired with Explicit State
  3. Hoare Semantics Switch Immediately while Mesa Semantics Only Hint
  4. Evolution from Theory into Language Features
  5. Example
  6. Exercise

Official chapter PDF

How a Monitor Automatically Guarantees Mutual Exclusion

A monitor places shared variables together with the methods that manipulate them inside a single module. Entry into any method implicitly acquires the module lock and exit releases it, so at most one thread ever executes inside the module, eliminating concurrent modification of the shared data.

Condition Variables Must Be Paired with Explicit State

A lock alone is insufficient; threads also need to sleep when a buffer is full or empty. Monitors therefore supply condition variables, yet those variables hold no count of their own, so an extra integer state variable must be maintained and inspected before a thread decides to wait.

Hoare Semantics Switch Immediately while Mesa Semantics Only Hint

Under Hoare semantics a signal instantly hands the lock and control to one waiter and the signaller pauses. Mesa semantics treat signal as a hint: the signaller keeps running until it leaves the module and the waiter is scheduled later, so the waiter must re-test the condition after waking.

Evolution from Theory into Language Features

The original theoretical design favoured ease of proof; later systems languages switched to Mesa style for simpler implementation. Languages such as Java now offer a close analogue via synchronized methods, yet programmers must still use wait/notify together with loop checks.

Pitfalls

  • Using if instead of while to test the condition under Mesa semantics, so a thread proceeds after another thread has already invalidated the condition.
  • Treating a condition variable like a semaphore and omitting an independent state counter, which produces permanent waits or incorrect wake-ups.

Run an example

Minimum C11 · complete program · Download .c

#include <stdio.h>
#include <pthread.h>

int balance = 0;
pthread_mutex_t mon = PTHREAD_MUTEX_INITIALIZER;

void deposit(int n) {
    pthread_mutex_lock(&mon);
    balance += n;
    pthread_mutex_unlock(&mon);
}

void *worker(void *arg) { (void)arg;
    for (int i = 0; i < 1000; i++)
        deposit(1);
    return NULL;
}

int main(void) {
    pthread_t t1, t2;
    pthread_create(&t1, NULL, worker, NULL);
    pthread_create(&t2, NULL, worker, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    printf("%d\n", balance);
    return 0;
}

Compile locally

gcc -std=c11 -Wall -Wextra -Wpedantic -Werror -pthread ostep-monitors.c -o example && ./example

Expected result

2000

CHECK YOUR UNDERSTANDING

Close the answer. Explain it.

Why must a bounded-buffer monitor that uses Mesa semantics write the “is the buffer empty” test as a while loop?

Show a reference answer

Because signal only moves the waiter to the ready queue and does not guarantee immediate execution; another consumer may empty the buffer before the original waiter re-acquires the lock, so the state must be re-checked.

Check the sources

Drafts and official chapters change. The version mark is only the example’s minimum.

Back to the catalog