outline
play

Outline 0024 Spring 2010 10 :: 2 Recall 0024 Spring 2010 10 - PowerPoint PPT Presentation

Outline 0024 Spring 2010 10 :: 2 Recall 0024 Spring 2010 10 :: 3 0024 Spring 2010 10 :: 4 0024 Spring 2010 10 :: 5 Dekker: core classes class Insist { private


  1. Outline �� 0024 Spring 2010 � – 10 :: 2 – �

  2. Recall � 0024 Spring 2010 � – 10 :: 3 – �

  3. 0024 Spring 2010 � – 10 :: 4 – �

  4. 0024 Spring 2010 � – 10 :: 5 – �

  5. Dekker: core classes � class Insist { private volatile int winner; void setWinner(int id) { winner = id; } int getWinner() { return winner;} } class Turn { private volatile int flag = 1; private final Insist insist; Turn (Insist a) { insist = a; } // continued 0024 Spring 2010 � – 10 :: 6 – �

  6. Dekker: core classes , part 2 � void request() { flag = 0;} void free() { flag = 1; } int read() { return flag; } void setWinner(int id) { insist.setWinner(id); } int getWinner() { return insist.getWinner(); } } 0024 Spring 2010 � – 10 :: 7 – �

  7. public void run() { � Worker int nextid; if (myid==0) {nextid = 1;} else {nextid=0;}; while (true) { mysignal.request(); while (true) { if (othersignal.read() == 1) break; if (mysignal.getWinner() == nextid) { mysignal.free(); while (true) { if (mysignal.getWinner() == myid) break; }; // other thread won 1st round mysignal.request(); } 0024 Spring 2010 � – 10 :: 8 – � }

  8. Worker, continued � // critical section mysignal.free(); mysignal.setWinner(nextid); } // end loop } } 0024 Spring 2010 � – 10 :: 9 – �

  9. Master � class Dekker { public static void main(String[] args) { Insist arbiter = new Insist(); Turn gate0 = new Turn(arbiter); Turn gate1 = new Turn(arbiter); Thread t1 = new Thread(new Worker(0,gate0,gate1)); Thread t2 = new Thread(new Worker(1,gate1,gate0)); t1.start(); t2.start(); } 0024 Spring 2010 � – 10 :: 10 – � }

  10. Worker 0 � public void run() { while (true) { A1: s0.request(); while (true) { A2: if (s1.read() == 1) break; A3: if (s0.getWinner() == 1) { s0.free(); while (true) { if (s0.getWinner() == 0) break; }; // worker 1 won 1st round s0.request(); } // end check if worker 1 insists } A4: // critical section s0.free(); s0.setWinner(1); } // end loop 0024 Spring 2010 � – 10 :: 11 – � } // end run

  11. Worker 1 � public void run() { while (true) { s1.request(); while (true) { if (s0.read() == 1) break; if (s1.getWinner() == 0) { s1.free(); while (true) { if (s1.getWinner() == 1) break; }; // worker 0 won 1st round s1.request(); } // end check if worker 0 insists } // critical section s1.free(); s1.setWinner(0); } // end loop 0024 Spring 2010 � – 10 :: 12 – � } // end run

  12. Can both threads enter the critical section? � 0024 Spring 2010 � – 10 :: 13 – �

  13. 0024 Spring 2010 � – 10 :: 14 – �

  14. Temporal logic � We want to show that there is no starvation. � Must reason that an event (start of critical section) will happen eventually. � E.g., for worker 0 we must show that once A1 is executed eventually A4 is reached � � Must show the same for Thread B … � 0024 Spring 2010 � – 10 :: 15 – �

  15. Worker 0 � public void run() { while (true) { A1: s0.request(); while (true) { A2: if (s1.read() == 1) break; A3: if (s0.getWinner() == 1) { s0.free(); while (true) { if (s0.getWinner() == 0) break; }; // worker 1 won 1st round s0.request(); } // end check if worker 1 insists } A4: // critical section s0.free(); s0.setWinner(1); } // end loop 0024 Spring 2010 � – 10 :: 16 – � } // end run

  16. Notation � � p means “p is always true” � � p means “p is eventually true” � Shorthand to save us typing � 0024 Spring 2010 � – 10 :: 17 – �

  17. Notation � � p means “p is always true” � � � After p turns true we read the value “true” whenever we want to � � q means “q is eventually true” � � � No statement how long q will remain true. � Often we must show � � p � � � Eventually p turns true and will remain true as long as we care to check it � Example: � � � � � p , � � q ⇒ � �� ( p � � q ) � 0024 Spring 2010 � – 10 :: 18 – �

  18. Absence of starvation � 0024 Spring 2010 � – 10 :: 19 – �

  19. Lemma 1 � 0024 Spring 2010 � – 10 :: 20 – �

  20. 0024 Spring 2010 � – 10 :: 21 – �

  21. Lemma 2 � 0024 Spring 2010 � – 10 :: 22 – �

  22. Proof of freedom from starvation � 0024 Spring 2010 � – 10 :: 23 – �

  23. Proof, continued � 0024 Spring 2010 � – 10 :: 24 – �

  24. Proof, continued � 0024 Spring 2010 � – 10 :: 25 – �

  25. Semaphores � Programming with critical sections is hard (impossible). � Better abstractions are needed. � � � We have seen the event queues in Java � � � We now look at another primitive � � � More comfortable than critical sections based on Dekker � s solution yet still not too complicated � Idea: a semaphore S is an integer-valued variable with two operations � � � P(S): if S>0 then S:= S-1 � else suspend thread � � � V(S): if (there are suspended threads) then wake one of them � else S = S+1 � 0024 Spring 2010 � – 10 :: 26 – �

  26. Semaphores - operations � P: wait, V: signal � P(S) and V(S) are atomic � � � No interruption � S must be given a non-negative starting value (S 0 ) � V(S) wakes up one thread -- no way to specify which one � Binary semaphores: S is intitalized with 1 � � � Legal values are 0 and 1 � 0024 Spring 2010 � – 10 :: 27 – �

  27. Semaphore invariants � i) � S � 0 � ii) � S = S 0 + #V(S) - #P(S) � 0024 Spring 2010 � – 10 :: 28 – �

  28. Semaphore use � It � s easy to make programming mistakes: forget a V(S) and no other thread will be able to make progress � � � Other threads remain suspended on S forever � Model of a program � loop { � � non_critical_section � � P(S) � � critical section � V(S) � } � 0024 Spring 2010 � – 10 :: 29 – �

  29. Properties � Mutual exclusion � � � Let S be a binary semaphore (i.e. S 0 = 1) � � � Proof: Let #T be the number of threads in their critical sections. Show that (#T + S == 1) is invariant. � � � Since S � 0 it follows that #T � 1. � � � Show that (#T + S == 1) is invariant: � � � #T == #P(S) - #V(S) � � � S == 1 + #V(S) - #P(S) � � � S == 1 - #T � � � #T + S == 1 � Absence of deadlock � Absence of starvation of a thread � 0024 Spring 2010 � – 10 :: 30 – �

  30. N threads � Solution with semaphores works for N threads � � � Our proof did not rely on the number of threads � Recall our different kinds of fairness - corresponding classes of semaphores � 0024 Spring 2010 � – 10 :: 31 – �

  31. Semaphores � Blocked-set semaphore: (Model used so far) V(S) wakes up one of the suspended threads � Blocked-queue semaphore: Suspended threads are kept in a FIFO queue, wake up in order of suspension � � � P(S): if (S >0) S-- else {append to tail of queue} � � � V(S): if ( ∃ suspended threads) {wake up thread at head of queue, remove it from queue} else S++ � Busy-wait semaphore: Value of S tested in busy wait loop (the if-stmt executes atomically but different threads may execute their if-stmt in interleaved manner) � � � � P(S): while (true) { � � � � if (S>0) { S=S-1; break;} } � � � V(S): S++ � 0024 Spring 2010 � – 10 :: 32 – �

  32. Properties � For a busy-wait semaphore, starvation is possible. � 0024 Spring 2010 � – 10 :: 33 – �

  33. “Dining Philosophers” � N philosophers (e.g., N==5) � N (5) study rooms � 1 dining room � 1 dining table with N (5) bowls and N (5) forks � � � Bowls and forks remain on table � Simple life of a philosopher: � while (true) { � // think � // eat � } � 0024 Spring 2010 � – 10 :: 34 – �

  34. Rules � A philosopher eats only if s/he has two forks � � � Needs those to heap pasta into the bowl � � � Once a philosopher has a fork, s/he hangs on to it until s/he can eat � No two philosophers may hold the same fork simultaneously � Your task: organize the life of the philosophers � No deadlock � No individual starvation � Efficient behavior (access to food) in the absence of contention � 0024 Spring 2010 � – 10 :: 35 – �

  35. Dining table � 0024 Spring 2010 � – 10 :: 36 – �

  36. Idea � 0024 Spring 2010 � – 10 :: 37 – �

  37. Semaphore solution 1 Semaphore [] fork = new Semaphore[5]; // Default semaphore is binary // Philosopher I (0 � I � 4) while (true) { // think fork[i].p(); // right fork fork[mod(i+1,5)].p(); // left fork // eat fork[i].v(); fork[mod(i+1,5)].v(); } 0024 Spring 2010 � – 10 :: 38 – �

  38. Problem: Deadlock � 0024 Spring 2010 � – 10 :: 39 – �

  39. Deadlock avoidance � Limit number of philosophers in dining room � � � � additional semaphore to control room occupancy � Semaphore [] fork = new Semaphore[4]; Semaphore room = new Semaphore(4); // init to 4 // Philosopher i: while (true) { // think room.p(); fork[i].p(); fork[mod(i+1,5)].p(); // eat fork[i].v(); fork[mod(i+1,5)].v(); room.v(); } 0024 Spring 2010 � – 10 :: 40 – �

Recommend


More recommend