- 2068 Bhadra · 8 marks
Monitor; dining philosophers with semaphore
Short answer
A monitor is a high-level module of procedures and data with automatic mutual exclusion; condition variables and wait/signal synchronize processes. The semaphore solution for dining philosophers uses a mutex, state array (thinking, hungry, eating) and per-philosopher semaphores; a philosopher eats only if neighbors are not eating, avoiding deadlock.
What is a monitor? Solve the dining philosopher's problem using semaphore.
Monitor
A monitor is a high-level synchronization construct: a package of procedures, variables and data structures, with the rule that only one process may be active in the monitor at any instant. The compiler adds the mutual exclusion automatically, so the programmer does not code locks. Inside it, condition variables with the operations wait(c) (block and release the monitor) and signal(c) (wake one waiting process) are used to synchronize processes. Example: producer-consumer with insert() and remove() procedures.
Dining philosophers using semaphores
Five philosophers alternate between thinking and eating; each needs the two forks beside him. A philosopher may eat only if neither neighbour is eating. The solution below uses an array state[], a mutex for the critical regions, and one semaphore per philosopher on which he blocks when forks are not available. It avoids deadlock; neighbours are tested whenever forks are put down.
#define N 5 /* number of philosophers */
#define LEFT (i+N-1)%N /* left neighbour of i */
#define RIGHT (i+1)%N /* right neighbour of i */
#define THINKING 0
#define HUNGRY 1
#define EATING 2
typedef int semaphore;
int state[N]; /* state of each philosopher */
semaphore mutex = 1; /* protects critical regions */
semaphore s[N]; /* one semaphore per philosopher, all 0 */
void philosopher(int i) {
while (TRUE) {
think();
take_forks(i); /* get both forks or block */
eat();
put_forks(i); /* release forks */
}
}
void take_forks(int i) {
down(&mutex);
state[i] = HUNGRY;
test(i); /* try to acquire both forks */
up(&mutex);
down(&s[i]); /* block if forks were not acquired */
}
void put_forks(int i) {
down(&mutex);
state[i] = THINKING;
test(LEFT); /* can left neighbour eat now? */
test(RIGHT); /* can right neighbour eat now? */
up(&mutex);
}
void test(int i) {
if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) {
state[i] = EATING;
up(&s[i]);
}
}
Explanation
take_forks(i): inside the mutex, the philosopher sets HUNGRY and callstest(i). If left and right neighbours are not eating, he sets EATING and doesup(s[i]). Then he leaves the mutex and doesdown(s[i]); this passes immediately if he got the forks, otherwise he blocks.put_forks(i): sets THINKING and tests the left and right neighbours. A hungry neighbour who can now eat is woken byup(s[neighbour]).- Two non-adjacent philosophers can eat together, so concurrency is maximum, and the forks are never held while waiting, so deadlock cannot occur.
✓ Answer checked by Claude Opus 5.5 (high effort)
Related questions
- Dining philosophers problem and solution · Operating System, chapter 3 · asked 2×
- Readers-writers problem with semaphore · Operating System, chapter 3