250 likes | 785 Views
The Dining Philosophers Problem. The Dining Philosophers. Philosopher (int i) { while (TRUE) {// Think (wait for forks) then Eat P (fork[i]); // test left fork P (fork[(i+1) mod 5]); // test right fork eat(); V (fork[(i+1) mod 5]); V (fork[i]); } }
E N D
The Dining Philosophers Philosopher (int i) { while (TRUE) {// Think (wait for forks) then Eat P (fork[i]); // test left fork P (fork[(i+1) mod 5]); // test right fork eat(); V (fork[(i+1) mod 5]); V (fork[i]); } } semaphore fork[5] = (1,1,1,1,1); // create philosopher processes fork (philosopher, 1, 0); fork (philosopher, 1, 1); fork (philosopher, 1, 2); fork (philosopher, 1, 3); fork (philosopher, 1, 4); Deadlock
One Solution philosopher (int i) { while (TRUE) {// Think (wait for forks) then Eat j = i % 2; P (fork [(i+j) mod 5]); P (fork [(i+1-j) mod 5]); eat(); V (fork [(i+1-j) mod 5]); V (fork [(i+j) mod 5]); } } semaphore fork[5] = (1,1,1,1,1); fork (philosopher, 1, 0); fork (philosopher, 1, 1); fork (philosopher, 1, 2); fork (philosopher, 1, 3); fork (philosopher, 1, 4);
AND Synchronization • For n resources: Rn • Some Pi->Rj, maybe >1 in one critsec • order of P operations may cause deadlock • Using semaphores Si • Psimultaneous(S1, …, Sn)
Simultaneous Semaphores P_sim (semaphore S, int N) {L1: if ( (S[0]>=1)&& … &&(S[N-1]>=1) ) { for (i=0; i<N; i++) S[i]--; } else { Enqueue the calling thread in the queue for the first S[i] where S[i]<1; The calling thread is blocked while it is in the queue; // When the thread is removed from the queue Goto L1; // this is an algorithm, not code! } } V_sim (semaphore S, int N) {for (i=0; i<N; i++) {S[i]++; Dequeue all threads in the queue for S[i]; All such threads are now ready to run (but may be blocked again in Psimultaneous); } else {} }
Dining Philosophers Re-visited Philosopher (int i) {while (TRUE) { // Think & Eat Psim (fork[i], fork [(i+1) mod 5]); eat(); Vsim (fork[i], fork [(i+1) mod 5]); } } semaphore fork[5] = (1,1,1,1,1); fork(philosopher, 1, 0); fork(philosopher, 1, 1); fork(philosopher, 1, 2); fork(philosopher, 1, 3); fork(philosopher, 1, 4); Deadlock resolved
Mutex solutions-1 • First attempt:int turn = 0; // initial value for turn (the semaphore)/* process 0 */ /* processes 1 */{while(turn != 0) no-op; {while(turn != 1) no-op; /* critical section*/ /* critical section*/ turn = 1; turn = 0;} } Strict alternation between two processes via use of shared variable “turn”Mutual exclusion achievedTwo problems: • Performance determined by least active (slowest) process • If one process crashes outside of the critical section, the other will wait forever for the CS.
Mutex solutions-2 • Second attempt:/* process 0 */ /* processes 1 */{flag[0] = true; {flag[1] = true;while(flag[1]) no-op; while(flag[0]) no-op; /* critical section*/ /* critical section*/flag[0] = false; flag[1] = false;} } Crash outside CS will not indefinitely block other process • Mutual exclusion achievedQ: Is Deadlock caused by race to set flag[i]?
Correct (s/w) solution • See Dekker’s Algorithm: • Combines using the “turn” variable and flag[] variable. • Avoids mutual courtesy • “turn” guarantees mutual exclusion. • “flag[]” breaks strict alternation problem – if your flag is set to 1 and other flag is 0, then enter no matter what turn is. • In the event that a race causes flag[0] = flag[1] = 1, then there is no deadlock to get to the CS because turn will allow one of the processes to enter. • flag[i] is an indication of “intent” to enter.