Dining-Philosphers Solution using Monitors

The Dining Philosophers Problem is a classic synchronization problem in operating systems that illustrates the challenges of resource allocation among concurrent processes. It demonstrates how shared resources can lead to deadlock and starvation if not properly managed through synchronization mechanisms.

What is the Dining Philosophers Problem?

The problem involves five philosophers sitting around a circular table, each alternating between thinking and eating. There are five forks placed between the philosophers. To eat, each philosopher needs both the fork on their left and the fork on their right. The challenge is to design an algorithm that prevents deadlock and starvation while allowing philosophers to eat.

Dining Philosophers Setup P0 P1 P2 P3 P4 F0 F1 F2 F3 F4

What are Monitors?

A monitor is a high-level synchronization construct that provides mutual exclusion and coordination among concurrent processes. It encapsulates shared data and the procedures that operate on that data, ensuring that only one process can access the monitor at any given time.

Monitor Structure

monitor monitor_name {
   // shared variables
   
   procedure operation1(...) {
      // code
   }
   
   procedure operation2(...) {
      // code
   }
   
   initialization_code() {
      // initialize variables
   }
}

Condition Variables

Monitors use condition variables to coordinate processes when certain conditions are not met. Two primary operations are available:

  • wait() Suspends the calling process and releases the monitor lock

  • signal() Wakes up one waiting process

Philosopher States

Each philosopher can be in one of three states:

Philosopher State Transitions THINKING HUNGRY EATING wants to eat gets forks finishes eating

Monitor Solution Implementation

monitor DiningPhilosophers {
   enum {THINKING, HUNGRY, EATING} state[5];
   condition self[5];
   
   void pickup(int i) {
      state[i] = HUNGRY;
      test(i);
      if (state[i] != EATING) {
         self[i].wait();
      }
   }
   
   void putdown(int i) {
      state[i] = THINKING;
      test((i + 4) % 5);  // test left neighbor
      test((i + 1) % 5);  // test right neighbor
   }
   
   void test(int i) {
      if (state[(i + 4) % 5] != EATING &&
          state[i] == HUNGRY &&
          state[(i + 1) % 5] != EATING) {
         state[i] = EATING;
         self[i].signal();
      }
   }
   
   initialization_code() {
      for (int i = 0; i < 5; i++)
         state[i] = THINKING;
   }
}

DiningPhilosophers dp;

How the Solution Works

  • pickup(i) Philosopher i becomes HUNGRY and tests if both forks are available. If not, waits on condition variable.

  • putdown(i) Philosopher i returns to THINKING state and signals hungry neighbors to test if they can now eat.

  • test(i) Checks if philosopher i can transition from HUNGRY to EATING by verifying neighbors are not eating.

Advantages and Disadvantages

Advantages

  • Deadlock Prevention Ensures mutual exclusion and prevents circular wait conditions

  • Simplicity High-level construct that encapsulates synchronization logic

  • Built-in Mutual Exclusion Automatically provides exclusive access to monitor procedures

Disadvantages

  • Potential Starvation A philosopher may still wait indefinitely if neighbors eat frequently

  • Performance Overhead Monitor locks can introduce delays in high-contention scenarios

  • Language Dependency Not all programming languages provide native monitor support

Conclusion

The Dining Philosophers Problem using monitors demonstrates an elegant solution to classical synchronization challenges. Monitors provide built-in mutual exclusion and condition variables that prevent deadlock while maintaining code simplicity. Although potential starvation remains a concern, the monitor approach offers a robust foundation for concurrent programming solutions.

Updated on: 2026-03-17T09:01:38+05:30

12K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements