CoursifyCoursify

Semaphore and the Dining-Philosophers Solution Using Monitors

Semaphore and the Dining-Philosophers Solution Using Monitors

Verified Sources
May 27, 2026

A semaphore is a classic synchronization primitive used in operating systems to coordinate concurrent activities and protect critical sections.2 Conceptually, a semaphore is an integer-like abstract object manipulated only through atomic operations such as waitwait and signalsignal (also written as PP and VV), where waitwait may block a process when the resource is unavailable, and signalsignal may wake a blocked process when the resource becomes available.2

Semaphores are widely used for two related purposes: mutual exclusion and coordination. A binary semaphore behaves much like a mutex and can enforce one-at-a-time access, while a counting semaphore tracks multiple identical resources.2 However, semaphores are low-level and error-prone because they are often global objects separate from the shared state they protect; incorrect ordering of waitwait/signalsignal calls can lead to deadlock, missed intent, or difficult-to-debug race conditions.

A monitor is a higher-level abstraction that groups shared data, procedures, and synchronization rules together.2 Inside a monitor, only one thread is active at a time, which gives implicit mutual exclusion. To express waiting for logical conditions, monitors are extended with condition variables such as x.wait()x.wait() and x.signal()x.signal().2 This distinction matters: a condition variable does not “remember” a prior signal if no thread was waiting, unlike a semaphore operation that changes stored state.2

The Dining Philosophers problem illustrates why synchronization design matters.2 Five philosophers alternate between thinking and eating, and each needs two adjacent chopsticks to eat. A naive strategy can create circular waiting, causing deadlock if each philosopher picks up one chopstick and waits forever for the other. The monitor-based solution avoids this by allowing a philosopher to enter the eating state only when both neighbors are not eating, using per-philosopher condition variables and shared state transitions.2

Footnotes

  1. Semaphore (programming) - Wikipedia - Overview of semaphore semantics, wait/signal behavior, and synchronization role. 2 3

  2. Semaphores in Process Synchronization - GeeksforGeeks - Introductory explanation of semaphores in process synchronization.

  3. Lecture 6: Semaphores and Monitors - UC San Diego - Operating-systems lecture notes comparing locks, semaphores, monitors, and condition variables. 2 3 4 5

  4. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics. 2 3 4 5 6

  5. Condition Variables & Monitors - Virginia Tech - Explanation of condition-variable semantics, monitor behavior, and fairness considerations.

  6. Lecture 4: Monitors - Dublin City University - Notes clarifying differences between monitor condition variables and semaphores.

  7. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic. 2 3

Dining Philosophers Solution using Monitors in Operating System

Core Distinction

A semaphore stores availability state, while a condition variable coordinates waiting for a condition inside a monitor.2

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Lecture 4: Monitors - Dublin City University - Notes clarifying differences between monitor condition variables and semaphores.

What a Semaphore Is

Formally, a semaphore supports two atomic operations:2

wait(S):{SS1if resource unavailable, block callerwait(S): \begin{cases} S \leftarrow S - 1 \\ \text{if resource unavailable, block caller} \end{cases} signal(S):{SS+1if threads are waiting, wake onesignal(S): \begin{cases} S \leftarrow S + 1 \\ \text{if threads are waiting, wake one} \end{cases}

In operating-systems teaching material, semaphores are described as high-level synchronization mechanisms that block waiting threads instead of forcing them to spin continuously, making them more suitable than raw spinlocks for longer waits. They can be used to solve bounded-buffer, readers-writers, and signaling problems, but they have drawbacks: they mix mutual exclusion and scheduling logic, are not naturally tied to the protected data, and are therefore more prone to programmer mistakes.

A monitor improves structure by bundling the state and the operations on that state into one protected module.2 Inside a monitor, synchronization becomes state-oriented: instead of manually counting resources everywhere, code checks whether a condition on shared state is true, and waits if it is not.2 This approach is especially natural for the Dining Philosophers problem because the relevant condition is not “how many chopsticks exist,” but “whether both neighboring philosophers are not eating.”2

Footnotes

  1. Semaphore (programming) - Wikipedia - Overview of semaphore semantics, wait/signal behavior, and synchronization role.

  2. Lecture 6: Semaphores and Monitors - UC San Diego - Operating-systems lecture notes comparing locks, semaphores, monitors, and condition variables. 2 3 4

  3. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics. 2 3

  4. Lecture 4: Monitors - Dublin City University - Notes clarifying differences between monitor condition variables and semaphores.

  5. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Semaphore vs Monitor-Based Reasoning

Conceptual comparison of abstraction level and programming safety in OS synchronization literature

Why the Dining Philosophers Problem Is Hard

The problem models a system of competing processes sharing adjacent limited resources. Each philosopher alternates between thinking and eating, but to eat, philosopher ii must hold both the left and right chopsticks. The correctness requirements are:

  1. Safety: adjacent philosophers must not eat simultaneously.2
  2. Deadlock freedom: the system must avoid circular wait where everyone holds one resource and waits forever.
  3. Starvation freedom: no philosopher should be postponed indefinitely under a fair scheduling discipline.

A naive semaphore-like resource acquisition pattern can fail because each philosopher may independently grab one chopstick first, satisfying hold-and-wait and circular-wait conditions. The monitor solution instead reasons over philosopher states:

  • THINKINGTHINKING
  • HUNGRYHUNGRY
  • EATINGEATING2

The key invariant is that philosopher ii may enter EATINGEATING only if both neighbors are not EATINGEATING.2 This eliminates the need to model chopsticks explicitly; the state array is sufficient because a philosopher eating implies both adjacent chopsticks are logically in use.2

Footnotes

  1. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic. 2 3 4 5 6 7

  2. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics. 2 3 4

  3. CS170 Lecture Notes -- Thinking and Eating - UC Santa Barbara - Notes explaining the state-based monitor solution and why explicit chopstick tracking is unnecessary.

Algorithm: Dining-Philosophers Solution Using a Monitor

  1. 1
    Step 1

    Create an array state[i]state[i] for all philosophers, where each entry is one of THINKINGTHINKING, HUNGRYHUNGRY, or EATINGEATING. Also create one condition variable self[i]self[i] per philosopher so each philosopher can wait independently.2

    Footnotes

    1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

    2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

  2. 2
    Step 2

    When philosopher ii wants to eat, it enters the monitor and sets state[i]=HUNGRYstate[i] = HUNGRY. It then calls test(i)test(i) to check whether both neighbors are not eating.2

    Footnotes

    1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

    2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

  3. 3
    Step 3

    The test(i)test(i) procedure grants eating only if state[left(i)] eqEATINGstate[left(i)] \ eq EATING, state[i]=HUNGRYstate[i] = HUNGRY, and state[right(i)] eqEATINGstate[right(i)] \ eq EATING. If true, set state[i]=EATINGstate[i] = EATING and signal self[i]self[i].2

    Footnotes

    1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

    2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

  4. 4
    Step 4

    If philosopher ii is still not in state EATINGEATING after the test, it executes self[i].wait()self[i].wait(). This releases the monitor and suspends the philosopher until another philosopher signals that conditions may now permit eating.2

    Footnotes

    1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

    2. Condition Variables & Monitors - Virginia Tech - Explanation of condition-variable semantics, monitor behavior, and fairness considerations.

  5. 5
    Step 5

    When philosopher ii finishes, it re-enters the monitor, sets state[i]=THINKINGstate[i] = THINKING, and calls test(left(i))test(left(i)) and test(right(i))test(right(i)). This gives hungry neighbors the chance to proceed if their constraints are now satisfied.2

    Footnotes

    1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

    2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

  6. 6
    Step 6

    Each philosopher repeatedly cycles through thinking, pickup, eating, and putdown. Because monitor entry is mutually exclusive and eating is granted only when both adjacent philosophers are not eating, the algorithm preserves safety and avoids the classic deadlock pattern.2

    Footnotes

    1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

    2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Monitor Pseudocode

The textbook-style monitor solution is commonly written as follows:2

1monitor DiningPhilosophers 2{ 3 enum { THINKING, HUNGRY, EATING } state[5]; 4 condition self[5]; 5 6 int left(int i) { return (i + 4) % 5; } 7 int right(int i) { return (i + 1) % 5; } 8 9 void test(int i) { 10 if (state[i] == HUNGRY && 11 state[left(i)] != EATING && 12 state[right(i)] != EATING) { 13 state[i] = EATING; 14 self[i].signal(); 15 } 16 } 17 18 void pickup(int i) { 19 state[i] = HUNGRY; 20 test(i); 21 if (state[i] != EATING) 22 self[i].wait(); 23 } 24 25 void putdown(int i) { 26 state[i] = THINKING; 27 test(left(i)); 28 test(right(i)); 29 } 30}

Each philosopher executes the following loop:2

1while (true) { 2 think(); 3 DiningPhilosophers.pickup(i); 4 eat(); 5 DiningPhilosophers.putdown(i); 6}

This algorithm relies on two monitor principles. First, monitor procedures execute with implicit mutual exclusion, so updates to state[]state[] are serialized.2 Second, condition variables allow a philosopher to sleep until another philosopher changes the relevant shared state.2

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics. 2 3 4

  2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic. 2

  3. Lecture 6: Semaphores and Monitors - UC San Diego - Operating-systems lecture notes comparing locks, semaphores, monitors, and condition variables.

  4. Condition Variables & Monitors - Virginia Tech - Explanation of condition-variable semantics, monitor behavior, and fairness considerations.

Important Semantics Detail

Condition-variable signalsignal is not the same as semaphore signalsignal. If no thread is waiting on a condition variable, the signal is not stored for later use.2

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Lecture 4: Monitors - Dublin City University - Notes clarifying differences between monitor condition variables and semaphores.

Semaphores expose synchronization as explicit waitwait/signalsignal operations on shared counters or binary flags. They are powerful, but the programmer must manually connect them to the shared state being protected.2

Footnotes

  1. Semaphore (programming) - Wikipedia - Overview of semaphore semantics, wait/signal behavior, and synchronization role.

  2. Lecture 6: Semaphores and Monitors - UC San Diego - Operating-systems lecture notes comparing locks, semaphores, monitors, and condition variables.

Why the Monitor Algorithm Works

The monitor solution is considered deadlock-free because no philosopher is allowed to partially acquire only one chopstick; eating begins only when both adjacent resources are effectively available.2 That breaks the classic circular-wait scenario that causes deadlock in naive approaches. The monitor also ensures mutual exclusion over the shared state array, so race conditions in state transitions are prevented.2

A useful correctness argument is based on invariants:

  • If state[i]=EATINGstate[i] = EATING, then state[left(i)]EATINGstate[left(i)] \neq EATING and state[right(i)]EATINGstate[right(i)] \neq EATING.2
  • Only one monitor procedure manipulates state[]state[] at a time.
  • A hungry philosopher waits only when its eligibility predicate is false.2

When philosopher ii finishes eating and calls putdown(i)putdown(i), the algorithm immediately tests both neighbors.2 This is important because it localizes responsibility: only the neighboring philosophers could have been blocked by philosopher ii's eating. If one of them is hungry and both of its neighbors are now not eating, it can be signaled to proceed.2

Starvation is subtler. The classic monitor formulation is deadlock-free, and under fair signaling and scheduling assumptions it is often presented as starvation-resistant in teaching contexts, but starvation freedom can depend on implementation semantics and scheduling policy.2 In practice, fairness strategies such as FIFO condition queues or explicit aging may be added if strict starvation-freedom guarantees are required.

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics. 2 3 4 5 6 7 8

  2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic. 2 3 4 5

  3. Lecture 6: Semaphores and Monitors - UC San Diego - Operating-systems lecture notes comparing locks, semaphores, monitors, and condition variables.

  4. Condition Variables & Monitors - Virginia Tech - Explanation of condition-variable semantics, monitor behavior, and fairness considerations. 2

  5. CS170 Lecture Notes -- Thinking and Eating - UC Santa Barbara - Notes explaining the state-based monitor solution and why explicit chopstick tracking is unnecessary.

Lifecycle of a Philosopher in the Monitor Solution

Thinking

Phase 1

The philosopher is outside the critical competition for chopsticks and does not request any shared resource."

Footnotes

  1. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Hungry

Phase 2

The philosopher enters the monitor, records intent by setting state[i]=HUNGRYstate[i] = HUNGRY, and asks whether both neighbors are not eating.2"

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Conditional Wait or Immediate Grant

Phase 3

If the eligibility predicate is false, the philosopher waits on self[i]self[i]; otherwise it transitions to EATINGEATING.2"

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Condition Variables & Monitors - Virginia Tech - Explanation of condition-variable semantics, monitor behavior, and fairness considerations.

Eating

Phase 4

The philosopher consumes the meal while the state invariant guarantees that adjacent philosophers are not eating.2"

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Putdown and Neighbor Wakeup

Phase 5

After eating, the philosopher sets its state to THINKINGTHINKING and tests both neighbors to enable newly feasible progress.2"

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Common Questions and Edge Cases

Exam-Oriented Insight

In the monitor solution, the crucial procedure is test(i)test(i). It encodes the safety predicate directly: philosopher ii may eat iff it is hungry and both neighbors are not eating.2

Footnotes

  1. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics.

  2. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic.

Summary Comparison

The central conceptual progression is:

ConceptPurposeKey OperationsMain Limitation
Lock / mutexMutual exclusion onlylock, unlockDoes not express waiting for complex conditions
SemaphoreMutual exclusion and signalingwaitwait, signalsignalError-prone and loosely coupled to data2
Monitor + condition variablesStructured synchronization around shared stateprocedure entry, waitwait, signalsignalSemantics depend on monitor model and fairness policy2

For the Dining Philosophers problem, monitors provide a more declarative solution than plain semaphores. Instead of counting forks directly, the algorithm maintains shared logical state and suspends philosophers until the predicate for safe eating becomes true.3 This makes the reasoning clearer: the algorithm enforces the invariant that no two adjacent philosophers are in the EATINGEATING state at the same time.2

Footnotes

  1. Lecture 6: Semaphores and Monitors - UC San Diego - Operating-systems lecture notes comparing locks, semaphores, monitors, and condition variables. 2

  2. Semaphore (programming) - Wikipedia - Overview of semaphore semantics, wait/signal behavior, and synchronization role.

  3. Dining Philosophers, Monitors, and Condition Variables - University of Colorado Boulder - Detailed lecture notes with monitor-based Dining Philosophers pseudocode and condition-variable semantics. 2 3

  4. Condition Variables & Monitors - Virginia Tech - Explanation of condition-variable semantics, monitor behavior, and fairness considerations.

  5. Dining-Philosophers Solution Using Monitors - GeeksforGeeks - Summary of the monitor solution, philosopher states, and deadlock-avoidance logic. 2

  6. CS170 Lecture Notes -- Thinking and Eating - UC Santa Barbara - Notes explaining the state-based monitor solution and why explicit chopstick tracking is unnecessary.

Knowledge Check

Question 1 of 4
Q1Single choice

What is the primary purpose of a semaphore in operating systems?

Explore Related Topics

1

The Banker's Algorithm: Deadlock Avoidance in Operating Systems

The Banker's Algorithm is a deadlock‑avoidance method that keeps a system in a safe state by checking each resource request against the maximum declared needs of processes.

  • Maintains Available, Max, Allocation, and Need matrices, where Need[i][j]=Max[i][j]Allocation[i][j]\text{Need}[i][j]=\text{Max}[i][j]-\text{Allocation}[i][j].
  • The Safety Algorithm uses vectors Work and Finish to find an execution order; if all processes finish, the state is safe.
  • The Resource‑Request Algorithm simulates allocation, runs the safety check, and commits only if the resulting state remains safe.
  • Time complexity of the safety check is O(m×n2)O(m \times n^{2}).
  • In practice the algorithm is rarely used because processes must predeclare maximum needs and the algorithm’s overhead is high.
2

Master Class: System Design for Software Engineers

The master class teaches software engineers how to design scalable, reliable distributed systems, covering architecture, scaling, trade‑offs, and interview techniques.

  • Horizontal scaling introduces state, partition, and consistency challenges.
  • CAP vs PACELC guide consistency, availability, and latency choices.
  • Redundancy, load balancers, caches, and async messaging avoid SPOFs.
  • SQL provides ACID with vertical scaling; NoSQL offers BASE and horizontal scaling.
  • Interview steps: clarify requirements, sketch design, deep‑dive components, add resiliency, optimize P99 latency.
3

Writing a C Program with `fork()` to Demonstrate the Parent-Child Relationship of Processes

Chat with Kiro