Sei sulla pagina 1di 9

Distributed Computing Spring 2009: Solutions to Assignment No.

1
Due Date: 3.8.09 April 2, 2009
Exercise 1: Programmers at the Flaky Computer Corporation designed the protocol shown in Fig. 1 to achieve n-thread mutual exclusion. For each of the following questions, either sketch a proof, or display an execution where it fails. a. Does this protocol satisfy mutual exclusion? b. Is this protocol deadlock free? c. Is this protocol starvation free? 1 class Flaky implements Lock { 2 private int turn; 3 private boolean busy = false; 4 public void lock () { 5 int me = ThreadId.get (); 6 do { 7 do { 8 turn = me; 9 } while (busy); 10 busy = true; 11 } while (turn = me); 12 } 13 public void unlock () { 14 busy = false; 15 } 16 } Figure 1: The Flaky lock used in Exercise 1 In proving the properties of this protocol, we consider location (line) 12 to be the Critical Section. 0

1 class Flaky implements Lock { 2 private int turn; 3 private boolean busy = false; 4 public void lock () { 5 int me = ThreadId.get (); 6 do { 7 do { 8 turn = me; 9 } while (busy); 10 busy = true; 11 } while (turn = me); 12 } 13 public void unlock () { 14 busy = false; 15 } 16 } Figure 2: The Flaky lock used in Exercise 1 Solution 1a: The protocol satises Mutual exclusion. To show this, we use a set of assertions that are jointly inductive. I1 I2 I3 I4 : i = j : : i = j : : i : : i : (at 12..14 [i] at 12..14 [j]) at 12..14 [i] turn = j at at 11 [i] busy turn = i at 12..14 [i] busy
6..9 [j]

Assertion I1 implies mutual exclusion. Solution 1b: The Flaky protocol can deadlock as follows:

Thread #1 proceeds to Line 11, with busy = 1, turn = 1. Then, thread #2 proceeds to Line 9, with busy = 1, turn = 2. Now, thread #1 nds turn = me and proceeds to Line 6. Both threads are now trapped within the loop spanning lines 79 without the ability to escape. This leads to a deadlock situation. Solution 1c: The Flaky protocol is not starvation free. This is since every protocol that can deadlock is not starvation free.

Exercise 2: Show that the Filter lock allows some threads to overtake others an arbitrary number of times. Solution 2: In order to solve this problem, you were expected to show a scenario in which some thread, say thread A, remains at some level while another thread, say thread B, gets into the critical section ahead of A an arbitrary number of times. In Fig. 3 we show such a scenario for an instance of the Filter protocol with 3 threads: A, B, and C. In this scenario.threads B and C overtake thread A an arbitrary number of times. A A B A B C

A B

A C

Figure 3: An overtaking scenario

Exercise 3: The M -exclusion problem is a variant of the starvation-free mutual exclusion problem. We make two changes: as many as M threads may be in the critical section at the same time, and fewer than M threads might fail (by halting) in the critical section. A solution to this problem must satisfy the following conditions: M -Exclusion: At any time, at most M threads are in the critical section. M -Starvation-Freedom: As long as fewer than M threads are in the critical section, then some thread that wants to enter the critical section will eventually succeed (even if some threads in the critical section have halted). Modify the n-thread Filter mutual exclusion algorithm to turn it into an M -exclusion algorithm. Under the M -Starvation-Freedom condition, does your solution guarantee that every thread that wants to get into the critical section will eventually succeed, as long as less than M threads have failed and remain stuck within the critical section?

Solution 3:

To modify the lter protocol into an M -exclusive lock, we can:

1. Remove the top M 1 levels from the protocol, and 2. Modify the test for progress by requiring that there are no more than M threads at the same level or higher (counting the testing thread itself) This can be done by a code such as the one presented in Fig. 4 1 class FilterM implements Lock { 2 int[ ] level; int[ ] victim; 3 public FilterM (int n, int m) { 4 level = new int[n]; victim = new int[n m]; 5 for (int i = 0; i < n; i++) { 6 level[i] = 0; } 7 } 8 public void lock ( ) { 9 int me = ThreadId.get ( ); 10 for (int i = 0; i < n m; i++) { 11 level[me] = i; 12 victim[i] = me; 13 //Spin while conicts exist 14 await (victim[i] = me |{k | level [k] i}| M ) 15 } 16 } 17 public void unlock ( ) { 18 int me = ThreadId.get ( ); 19 level[me] = 0; 20 } 21 } Figure 4: An M -exclusion lter-like lock

Exercise 4: In practice, almost all lock acquisitions are uncontended, so the most practical measure of a locks performance is the number of steps needed for a thread to acquire a lock when no other thread is concurrently trying to acquire the lock. Scientists at Cantaloupe-Mellon University have devised the following wrapper for an arbitrary lock, shown in Fig. 5. They claim that if the base Lock class provides mutual exclusion and is starvation-free, so does the FastPath lock, but it can be acquired in a constant number of steps in the absence of contention. Sketch an argument why they are right, or give a counterexample. We assume that the implementation of the basic lock Lock accepts an invocation of the unlock method even if there was no corresponding preceding lock . 4

1 class FastPath implements Lock { 2 private static ThreadLocal < Integer > myIndex ; 3 private Lock lock ; 4 private int x, y = 1; 5 public void wrap lock () { 6 int i = myIndex .get (); 7 x = i; // Im here 8 await (y == 1); // Is the lock free? 9 y = i; // me again? 10 if (x = i); // Am I still here? 11 lock .lock (); // slow path 12 } 13 public void wrap unlock () { 14 y = 1; 15 lock .unlock (); 16 } 17 } Figure 5: Fast Path mutual exclusion algorithm used in Exercise 4 Solution 4: The FastPath protocol may violate both mutual exclusion and starvation freedom, so it is entirely unacceptable. Violation of mutual exclusion can be caused when threads A and B both reach Line 9 at about the same time. One will nd x = i and proceed to its critical section without locking. The other will invoke lock .lock and also proceed to the critical section. Thus both A and B may execute their critical sections at the same time. Violation of starvation freedom may result when some thread, say thread A, may remain stuck forever at Line 8, waiting for y to become 1. In parallel, other threads may get in and out of their respective critical sections. Exercise 5: Consider the class Bouncer presented in Fig. 6. Suppose n threads call the visit method of this class. Prove that a. At most one thread gets the value STOP. b. At most n 1 threads get the value DOWN. c. At most n 1 threads get the value RIGHT. Note that the last two proofs are not symmetric.

1 class Bouncer { 2 private static nal int DOWN = 0; 3 private static nal int RIGHT = 1; 4 private static nal int STOP = 2; 5 private boolean goRight = false; 6 private static ThreadLocal < Integer > myIndex ; 7 private int last = 1; 8 int visit() { 9 int i = myIndex .get (); 10 last = i; 11 if (goRight) 12 return RIGHT; 13 goRight = true; 14 if (last == i) 15 return STOP; 16 else 17 return DOWN; 18 } 19 } Figure 6: The Bouncer class implementation

Solution 5a: We show that at most one thread can return STOP. Assume thread A is the rst to return STOP. This implies that between the time A executed Line 10 (denoted t1 ) and the time it tested last == i (say at t2 > t1 ), no other thread executed Line 10. If any other thread, say B, also succeeded to return STOP, it must have executed L10 after t2 . However, by this time goRight = 1, so thread B must return RIGHT. Solution 5b: two cases: We show that at most n 1 threads get the value DOWN. We consider

1. At least one thread returned RIGHT. Then certainly, no more than n 1 could return DOWN. 2. Otherwise, all threads must have passed Line 11 before any of them executed Line 13. This implies that at some point, all threads must have been concentrated at location 13. Then, the thread i such that last = i will return STOP, and all the rest will return DOWN. Solution 5c: We show that at most n 1 threads return the value RIGHT. The rst thread to execute Line 11 must output STOP or DOWN. So, at most n 1 can output RIGHT. 6

Exercise 6: In Fig. 7 we present a variant of the Bakery algorithm. Unlike the version presented in class, this version does not have the ag variable. Instead, it uses the value label [i] = 0 in order to signal that thread i is currently not interested to get into the critical section. Prove that this version of the Bakery algorithm maintains mutual exclusion. Alternately, present a counterexample, which is a computation violating mutual exclusion. 1 class Bakery implements Lock { 2 Label [ ]label ; 3 public Bakery(int n) { 4 label = newLabel [n]; 5 for (int i = 0; i < n; i + +) 6 label [i] = 0; 7 } 8 public void lock () { 9 int i = ThreadId.get(); 10 label[i] = max(label[0], . . . , label[n1]) + 1; 11 await (k = i : label [k] = 0 (label[i], i) (label [k], k)); 12 } 13 public void unlock () { 14 label[i] = 0; 15 } 16 } Figure 7: A variant of the Bakery Algorithm

Solution 6: The reason that this variant of the Bakery algorithm may violate mutual exclusion is that we cannot assume that the statement at Line 10 is executed atomically. In particular, it may very well be that the new value of the maximal label is rst computed in a temporary variable (call it temp), and only then stored in label[i]. Thus, execution of this program may be equivalent to that of the program presented in Fig. 8.

1 class Bakery implements Lock { 2 Label [ ]label ; 3 public Bakery(int n) { 4 label = newLabel [n]; 5 for (int i = 0; i < n; i + +) 6 label [i] = 0; 7 } 8 public void lock () { 9 int i = ThreadId.get(); 10 int temp = max(label[0], . . . , label [n1]); 11 label[i] = temp + 1; 12 await (k = i : label [k] = 0 (label[i], i) 13 } 14 public void unlock () { 15 label[i] = 0; 16 } 17 }

(label [k], k));

Figure 8: The Bakery Algorithm with explicit temp variable We will show how the program of Fig. 8 can violate mutual exclusion. Assume that thread 0 starts execution of method lock and reaches location L11 with label [0] = Bakery[0].temp = 0. Next, assume that thread 1 executes line 8, . . . , 11 and reaches location 12 with label [1] = 1. When executing the statement in Line 12 it nds that the labels of all other threads, in particular the label of thread 0, equal 0. Therefore, thread 1 enters its critical section. Next, thread 0 continues its execution from Line 11. It reaches location 12 with label[0] = 1. Comparing its label with the labels of all other threads, it nds that thread 0 has a label pair that is smaller (in lexicographic order) than the label pairs of all other non-idle threads. In particular, (1, 0) (1, 1). Hence, thread 0 is also admitted into the critical section, thus violating mutual exclusion.

Potrebbero piacerti anche