Dining-Philosophers Problem Shared data fork[5]: semaphore; initialized to 1
Relevance Dining philosopher’s problem models a large class of concurrency-control problems Highlights need for freedom from deadlock and starvation Early versions of FreeBSD failed to address this problem right, and hence parallelism was severely impacted
Simple and Obvious solution do { wait(fork[i]) wait(fork[(i+1) % 5]) … eat … signal(fork[i]); signal(fork[(i+1) % 5]); … think … } while (1); Problems with the solution?
Problems with the solution Not dead-lock free A Second Alternative – Use a back-off time – Problem? A Third Alternative – Use a random back-off time – Problem? Yet Another Alternative – Binary Semaphore – FreeBSD – Problem?
Tanenbaum’s solution (1/4) Datastructures – 3 States of phil are defined THINKING, HUNGRY, EATING – 2 Semaphores mutex – binary semaphore – Provides mutual exclusion in critical region – Initial value = 1 s[5] – array of semaphores – One semaphore per phil – Initial value=0 – Left Neighbor of ‘i’ (i+4)%5 – Right Neighbor of ‘i’ (i+1)%5
Tanenbaum’s solution (2/4) Philosopher process 'i‘ while(1) { think(); take_forks(i); /* Acquire both the forks or block */ eat(); put_forks(i); /* Put back both the forks on table */ }
Tanenbaum’s solution (3/4) Philosopher 'i' taking the fork wait(mutex);/* Enter critical section */ state[i]='HUNGRY'; test(i);/* Try to acquire 2 forks */ signal(mutex);/* Exit critical section */ wait(s[i]);/* Block if forks were not acquired */ Test procedure Test(i) { if ( state[i] == HUNGRY && state[(i+4)%5] != EATING && state[(i+1)%5] != EATING ) { state[i] = EATING; signal(s[i]); }
Tanenbaum’s solution (4/4) Philosopher 'i' putting down the fork wait(mutex);/* Enter critical section */ state[i]='THINKING';/* Phil has finished eating */ test( (i+4)%5 );/* See if left neighbour can now eat */ test( (i+1)%5 );/* See if right neighbour can now eat */ signal(mutex);/* Exit critical section */ This solution is deadlock free Provides for maximum parallelism when extended to any arbitrary ‘N’
Monitors Why Monitors? – Semaphores demand strict sequencing which are difficult to implement even in relatively simple scenarios – Monitors provide high level constructs that help write correct programs – Monitor is a collection of procedures, variables and data structures grouped together in a special kind of module – Processes may call procedures in a monitor but cannot directly access the data internal to a monitor from procedures declared outside a monitor (private data and public methods as in Java)
Bounded buffer Var f,e,s :semaphore (:=0); (In the begning s=1,f=0,e=n ) Producer Begin repeat produce; wait (e) wait(s) append; Signal(s); signal (f); forever End; Consumer Begin repeat wait(f); wait(s); take; signal(s); signal (e); consume; forever End;
Monitors – General Structure monitor monitor-name { //shared variable declarations procedure P1(...){... } procedure p2(...){... }. procedure pn(...){... } initialisation code(...){... } }//end of monitor
Monitors How do monitors achieve mutual exclusion? – Only one process is active in a monitor at any instant – Compiler handles calls to monitor procedures differently from other procedure calls – Compiler implements the mutual exclusion – Why is this an advantage over semaphores?? How to code monitors? – Just turn each critical region into a monitor procedure
Condition variables Why need them? – Provide means by which processes can block when they cannot proceed in a monitor Condition variables have two operations associated with them – wait and signal When a process cannot proceed it calls wait on some condition variable, X This could cause another process to enter the monitor and raise a signal on the same condition variable, X
What happens after a signal? Hoare’s Method – Run the newly awakened process Hansen’s Method – Process doing the signal must exit monitor immediately – how? – If signal is on a condition variable on which several processes are waiting? Third solution – Signaler runs and allow waiting process to start running only after signaler exits monitor
How is this different from Semaphore? Condition variables are not counters If a condition variable is signalled with no one waiting on it, the signal is lost
Monitor solution for Bounded Buffer