Presentation is loading. Please wait.

Presentation is loading. Please wait.

Mutual Exclusion Modified from Companion slides for

Similar presentations


Presentation on theme: "Mutual Exclusion Modified from Companion slides for"— Presentation transcript:

1 Mutual Exclusion Modified from Companion slides for
© 2003 Herlihy and Shavit Mutual Exclusion Modified from Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

2 © 2003 Herlihy and Shavit Mutual Exclusion Today we will try to formalize our understanding of mutual exclusion We will also use the opportunity to show you how to argue about and prove various properties in an asynchronous concurrent setting a number of classical mutual exclusion algorithms that work by reading and writing shared memory. Although these algorithms are not used in practice, we study them because they provide an ideal introduction to the kinds of correctness issues that arise in every area of synchronization. These algorithms, simple as they are, display subtle properties that students should understand before they are ready to approach the design of truly practical techniques.

3 © 2003 Herlihy and Shavit Mutual Exclusion In his 1965 paper E. W. Dijkstra wrote: "Given in this paper is a solution to a problem which, to the knowledge of the author, has been an open question since at least 1962, irrespective of the solvability. [...] Although the setting of the problem might seem somewhat academic at first, the author trusts that anyone familiar with the logical problems that arise in computer coupling will appreciate the significance of the fact that this problem indeed can be solved." Dijkstra was the first to provide a solution to the mutual exclusion problem. Computer coupling:程序模块间的互相依赖程度

4 Mutual Exclusion Formal problem definitions Solutions for 2 threads
© 2003 Herlihy and Shavit Mutual Exclusion Formal problem definitions Solutions for 2 threads Solutions for n threads Fair solutions Inherent costs

5 Warning You will never use these protocols
© 2003 Herlihy and Shavit Warning You will never use these protocols Get over it You are advised to understand them The same issues show up everywhere Except hidden and more complex

6 Why is Concurrent Programming so Hard?
© 2003 Herlihy and Shavit Why is Concurrent Programming so Hard? Try preparing a seven-course banquet By yourself With one friend With twenty-seven friends … Before we can talk about programs Need a language Describing time and concurrency

7 © 2003 Herlihy and Shavit Time “Absolute, true and mathematical time, of itself and from its own nature, flows equably without relation to anything external.” (I. Newton, 1689) “Time is, like, Nature’s way of making sure that everything doesn’t happen all at once.” (Anonymous, circa 1968) For the next set of slides, PLEASE READ THE DISCUSSION ABOUT TIME IN THE TEXTBOOK. Do not read this slide out. time

8 © 2003 Herlihy and Shavit Time Reasoning about concurrent computation is mostly reasoning about time Whether or not things happen simultaneously How multiple time intervals can overlap In our systems, no “time” of global clock Instead, we think of the world in terms of the ordering among events We will use “time” just as a tool for explaining this ordering in our systems there will not be time in the sense of a global clock that all threads can read and use in order to relate to each other, rather, we will think of the world in terms of the ordering among events, and will use time just as a tool for explaining this ordering. In other words, there is a notion of time but it is local and not global. In fact, we already know this from general relativity  time

9 Events An event a0 of thread A is Instantaneous
© 2003 Herlihy and Shavit Events An event a0 of thread A is Instantaneous No simultaneous events (break ties) a0 A thread is a state machine, and its state transitions are events. Instantaneous: occur at a single instant of time,瞬间的 As a practical matter, if we are unsure about the order of two events that happen very close in time, then any order will do. time

10 Threads A thread A is (formally) a sequence a0, a1, ... of events
© 2003 Herlihy and Shavit Threads A thread A is (formally) a sequence a0, a1, ... of events “Trace” model Notation: a0  a1 indicates order a0 a1 a2  is a total order on events time

11 Example Thread Events Assign to shared variable
© 2003 Herlihy and Shavit Example Thread Events Assign to shared variable Assign to local variable Invoke method Return from method Lots of other things …

12 Threads are State Machines
© 2003 Herlihy and Shavit Threads are State Machines a0 a3 Events are transitions a2 a1

13 States Thread State System state Program counter Local variables
© 2003 Herlihy and Shavit States Thread State Program counter Local variables System state Object fields (shared variables) Union of thread states

14 © 2003 Herlihy and Shavit Concurrency Thread A time Local views

15 Concurrency Thread A Thread B time time © 2003 Herlihy and Shavit
Local views

16 Interleavings Events of two or more threads Interleaved
© 2003 Herlihy and Shavit Interleavings Events of two or more threads Interleaved Not necessarily independent (why?) time

17 Intervals An interval A0 =(a0,a1) is Time between events a0 and a1 a0
© 2003 Herlihy and Shavit Intervals An interval A0 =(a0,a1) is Time between events a0 and a1 a0 a1 A0 time

18 © 2003 Herlihy and Shavit Intervals may Overlap b0 b1 B0 a0 a1 A0 time

19 Intervals may be Disjoint
© 2003 Herlihy and Shavit Intervals may be Disjoint b0 b1 B0 a0 a1 A0 time

20 Interval A0 precedes interval B0
© 2003 Herlihy and Shavit Precedence Interval A0 precedes interval B0 b0 b1 B0 a0 a1 A0 先后次序 time

21 Precedence Notation: A0  B0 Formally,
© 2003 Herlihy and Shavit Precedence Notation: A0  B0 Formally, End event of A0 before start event of B0 Also called “happens before” or “precedes” The “arrow” (HAPPENS BEFORE) notation was introduced by Leslie Lamport, a distributed computing pioneer.

22 Precedence Ordering Remark: A0  B0 is just like saying Oh wait,
© 2003 Herlihy and Shavit Precedence Ordering Remark: A0  B0 is just like saying 1066 AD  1492 AD, Middle Ages  Renaissance, Oh wait, what about this week vs this month? AD:公元。Renaissance:文艺复兴。 Week is concurrent with month, leads into next slide

23 Precedence Ordering Never true that A  A
© 2003 Herlihy and Shavit Precedence Ordering Never true that A  A If A B then not true that B A If A B & B C then A C Funny thing: A B & B A might both be false! In this slide we deal with concurrent events.

24 Partial Orders (you may know this already)
© 2003 Herlihy and Shavit Partial Orders (you may know this already) Irreflexive: Never true that A  A Antisymmetric: If A  B then not true that B  A Transitive: If A  B & B  C then A  C is a partial order on intervals. notice that it could be that both AB and BA don’t hold.

25 Total Orders (you may know this already)
© 2003 Herlihy and Shavit Total Orders (you may know this already) Also Irreflexive Antisymmetric Transitive Except that for every distinct A, B, Either A  B or B  A  is a total order on events. We strengthen antisymmetry which allowed that both AB and BA don’t hold by requiring that one of the two always hold.

26 Repeated Events a0k A0k k-th occurrence of event a0
© 2003 Herlihy and Shavit Repeated Events while (mumble) { a0; a1; } k-th occurrence of event a0 a0k k-th occurrence of interval A0 =(a0,a1) More notations A0k

27 The use of locks

28 Implementing a Counter
© 2003 Herlihy and Shavit Implementing a Counter public class Counter { private long value; public long getAndIncrement() { temp = value; value = temp + 1; return temp; } Make these steps indivisible using locks

29 Locks (Mutual Exclusion)
© 2003 Herlihy and Shavit Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } This is the formal definition of a mutual exclusion lock object in java.

30 Locks (Mutual Exclusion)
© 2003 Herlihy and Shavit Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } acquire lock

31 Locks (Mutual Exclusion)
© 2003 Herlihy and Shavit Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } acquire lock release lock Threads using the Lock() and Unlock() methods must follow a specific format, first Lock() then Unlock().

32 Using Locks public class Counter { private long value;
© 2003 Herlihy and Shavit Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Java “finally” block is *always* executed after the code in the preceding “try” block (no matter if the try block throws an exception, whether or not the exception is caught). try{…}catch{…}finally{…}: catch the exception, then do finally part. In Java, these methods should be used in the following structured way. mutex.lock(); try { // body } finally { mutex.unlock(); }

33 Using Locks acquire Lock public class Counter { private long value;
© 2003 Herlihy and Shavit Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} acquire Lock

34 Using Locks Release lock (no matter what) public class Counter {
© 2003 Herlihy and Shavit Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Release lock (no matter what)

35 Using Locks Critical section public class Counter {
© 2003 Herlihy and Shavit Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Critical section Critical section: a block of code that can be executed by only one thread at a time

36 © 2003 Herlihy and Shavit Mutual Exclusion Let CSik be thread i’s k-th critical section execution The interval CS^k_i is denoted by the .

37 © 2003 Herlihy and Shavit Mutual Exclusion Let CSik be thread i’s k-th critical section execution And CSjm be thread j’s m-th critical section execution

38 © 2003 Herlihy and Shavit Mutual Exclusion Let CSik be thread i’s k-th critical section execution And CSjm be j’s m-th execution Then either or

39 © 2003 Herlihy and Shavit Mutual Exclusion Let CSik be thread i’s k-th critical section execution And CSjm be j’s m-th execution Then either or CSik  CSjm

40 © 2003 Herlihy and Shavit Mutual Exclusion Let CSik be thread i’s k-th critical section execution And CSjm be j’s m-th execution Then either or CSik  CSjm CSjm  CSik

41 Deadlock-Freedom If some thread calls lock()
© 2003 Herlihy and Shavit Deadlock-Freedom If some thread calls lock() And never returns Then other threads must complete lock() and unlock() calls infinitely often System as a whole makes progress Even if individuals starve At least one other thread is completing infinitely often, since there are only a finite number of threads.

42 Starvation-Freedom If some thread calls lock()
© 2003 Herlihy and Shavit Starvation-Freedom If some thread calls lock() It will eventually return Individual threads make progress We want every individual to be happy, not just the system as a whole.

43 Two-Thread vs n -Thread Solutions
© 2003 Herlihy and Shavit Two-Thread vs n -Thread Solutions Two-thread solutions first Illustrate most basic ideas Fits on one slide Then n-Thread solutions

44 Two-Thread Conventions
© 2003 Herlihy and Shavit Two-Thread Conventions class … implements Lock { // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; } … will be the lock method we use

45 Two-Thread Conventions
© 2003 Herlihy and Shavit Two-Thread Conventions class … implements Lock { // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; } We will not mention i and j defs again Henceforth: i is current thread, j is other thread

46 LockOne class LockOne implements Lock { private boolean[] flag =
© 2003 Herlihy and Shavit LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } public void unlock() { flag[i] = false;

47 LockOne Set my flag class LockOne implements Lock {
© 2003 Herlihy and Shavit LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } public void unlock() { flag[i] = false; Set my flag

48 Wait for other flag to go false
© 2003 Herlihy and Shavit LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } public void unlock() { flag[i] = false; Set my flag Wait for other flag to go false

49 LockOne Satisfies Mutual Exclusion
© 2003 Herlihy and Shavit LockOne Satisfies Mutual Exclusion Assume CSAj overlaps CSBk Consider each thread's last (j-th and k-th) read and write in the lock() method before entering CS Derive a contradiction By way of contradiction we make an assumption: both are in the critical sections in overlapping intervals

50 From the Code writeA(flag[A]=true)  readA(flag[B]==false) CSA
© 2003 Herlihy and Shavit From the Code writeA(flag[A]=true)  readA(flag[B]==false) CSA writeB(flag[B]=true)  readB(flag[A]==false)  CSB class LockOne implements Lock { public void lock() { flag[i] = true; while (flag[j]) {} }

51 From the Assumption readA(flag[B]==false)  writeB(flag[B]=true)
© 2003 Herlihy and Shavit From the Assumption readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true)

52 Combining Assumptions: From the code
© 2003 Herlihy and Shavit Combining Assumptions: readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true) From the code writeA(flag[A]=true)  readA(flag[B]==false) writeB(flag[B]=true)  readB(flag[A]==false)

53 Combining Assumptions: From the code
© 2003 Herlihy and Shavit Combining Assumptions: readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true) From the code writeA(flag[A]=true)  readA(flag[B]==false) writeB(flag[B]=true)  readB(flag[A]==false)

54 Combining Assumptions: From the code
© 2003 Herlihy and Shavit Combining Assumptions: readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true) From the code writeA(flag[A]=true)  readA(flag[B]==false) writeB(flag[B]=true)  readB(flag[A]==false)

55 Combining Assumptions: From the code
© 2003 Herlihy and Shavit Combining Assumptions: readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true) From the code writeA(flag[A]=true)  readA(flag[B]==false) writeB(flag[B]=true)  readB(flag[A]==false)

56 Combining Assumptions: From the code
© 2003 Herlihy and Shavit Combining Assumptions: readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true) From the code writeA(flag[A]=true)  readA(flag[B]==false) writeB(flag[B]=true)  readB(flag[A]==false)

57 Combining Assumptions: From the code
© 2003 Herlihy and Shavit Combining Assumptions: readA(flag[B]==false)  writeB(flag[B]=true) readB(flag[A]==false)  writeA(flag[A]=true) From the code writeA(flag[A]=true)  readA(flag[B]==false) writeB(flag[B]=true)  readB(flag[A]==false)

58 Impossible in a partial order
© 2003 Herlihy and Shavit Cycle! Impossible in a partial order This is the same proof we did for Alice and Bob in the earlier lecture, but this time done formally…notice that we derive the contradiction from the cycle here, slightly different from the way this is done in the book.

59 Deadlock Freedom LockOne Fails deadlock-freedom
© 2003 Herlihy and Shavit Deadlock Freedom LockOne Fails deadlock-freedom Concurrent execution can deadlock Sequential executions OK flag[i] = true; flag[j] = true; while (flag[j]){} while (flag[i]){} The LockOne algorithm is subject to deadlock: if each thread sets its flag to true and waits for the other, they will wait forever, which is the classic definition of a deadlock. Recall that when we looked at the story of Alice and Bob and their pets, this was exactly the first, broken protocol we considered.

60 LockTwo public class LockTwo implements Lock { private int victim;
© 2003 Herlihy and Shavit LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {}

61 LockTwo Let other go first public class LockTwo implements Lock {
© 2003 Herlihy and Shavit LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} Let other go first

62 LockTwo Wait for permission public class LockTwo implements Lock {
© 2003 Herlihy and Shavit LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} Wait for permission

63 LockTwo Nothing to do public class Lock2 implements Lock {
© 2003 Herlihy and Shavit LockTwo public class Lock2 implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} Nothing to do

64 LockTwo Claims Satisfies mutual exclusion Not deadlock free
© 2003 Herlihy and Shavit LockTwo Claims Satisfies mutual exclusion If thread i in CS Then victim == j Cannot be both 0 and 1 Not deadlock free Sequential execution deadlocks Concurrent execution does not public void lock() { victim = i; while (victim == i) {}; } Sequential execution deadlocks because thread arriving alone will not get in. Concurrent one is OK since one always allows the other to have priority

65 Peterson’s Algorithm public void lock() { flag[i] = true; victim = i;
© 2003 Herlihy and Shavit Peterson’s Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; We now combine the two algorithms, one that does not deadlock when they are concurrent, and the other that does not deadlock when they are sequential, to derive an algorithm that never deadlocks.

66 Announce I’m interested
© 2003 Herlihy and Shavit Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false;

67 Announce I’m interested
© 2003 Herlihy and Shavit Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; Defer to other

68 Peterson’s Algorithm Announce I’m interested Defer to other
© 2003 Herlihy and Shavit Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; Defer to other Wait while other interested & I’m the victim

69 Peterson’s Algorithm Announce I’m interested Defer to other
© 2003 Herlihy and Shavit Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; Defer to other Wait while other interested & I’m the victim No longer interested

70 Mutual Exclusion Cannot both be true If thread 0 in critical section,
© 2003 Herlihy and Shavit Mutual Exclusion public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; If thread 0 in critical section, flag[0]=true, victim = 1 If thread 1 in critical section, flag[1]=true, victim = 0 Refer students to book for detailed proof. Cannot both be true

71 Deadlock Free Thread blocked One or the other must not be the victim
© 2003 Herlihy and Shavit Deadlock Free public void lock() { while (flag[j] && victim == i) {}; Thread blocked only at while loop only if it is the victim One or the other must not be the victim See proof details in book

72 © 2003 Herlihy and Shavit Starvation Free Thread i blocked only if j repeatedly re-enters so that flag[j] == true and victim == i When j re-enters it sets victim to j. So i gets in public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; See proof details in book

73 © 2003 Herlihy and Shavit Now let’s study two mutual exclusion protocols that work for n threads (n > 2). Filter lock Direct generalization of Peterson lock Bakery lock Filter lock: a direct generalization of the Peterson lock to multiple threads. Bakery lock, is perhaps the simplest and best known $n$-thread solution.

74 The Filter Algorithm for n Threads
© 2003 Herlihy and Shavit The Filter Algorithm for n Threads There are n-1 “waiting rooms” called levels At each level At least one enters level At least one blocked if many try Only one thread makes it through ncs cs The Filter lock creates n-1 ``waiting rooms'', called levels, that a thread must traverse before acquiring the lock. There are n-1 levels threads pass through, the last of which is the critical section. There are at most n threads that pass concurrently into level 0, n-1 into level 1 (a thread in level 1 is already in level 0), n-2 into level 2 and so on

75 Filter Thread 2 at level 4 n-1 level } victim
© 2003 Herlihy and Shavit Filter class Filter implements Lock { int[] level; // level[i] for thread i int[] victim; // victim[L] for level L public Filter(int n) { level = new int[n]; victim = new int[n]; for (int i = 1; i < n; i++) { level[i] = 0; }} } n-1 1 4 2 Thread 2 at level 4 level Peterson’s flag[i]: whether thread i is trying to enter CS. level[i]: the highest level that thread i is trying to enter. Each level L has victim[L] to “filter out” one thread, excluding it from level L. victim

76 Filter class Filter implements Lock { … public void lock(){
© 2003 Herlihy and Shavit Filter class Filter implements Lock { public void lock(){ for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i level[k] >= L) && victim[L] == i ); }} public void unlock() { level[i] = 0; There are n-1 levels threads pass through, the last of which is the critical section.

77 Filter One level at a time class Filter implements Lock { …
© 2003 Herlihy and Shavit Filter class Filter implements Lock { public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void unlock() { level[i] = 0; One level at a time

78 Announce intention to enter level L
© 2003 Herlihy and Shavit Filter class Filter implements Lock { public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); // busy wait }} public void unlock() { level[i] = 0; Announce intention to enter level L

79 Give priority to anyone but me
© 2003 Herlihy and Shavit Filter class Filter implements Lock { int level[n]; int victim[n]; public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void unlock() { level[i] = 0; Give priority to anyone but me

80 © 2003 Herlihy and Shavit Filter class Filter implements Lock { int level[n]; int victim[n]; public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void unlock() { level[i] = 0; Wait as long as someone else is at same or higher level, and I’m designated victim

81 Thread enters level L when it completes the loop
© 2003 Herlihy and Shavit Filter class Filter implements Lock { int level[n]; int victim[n]; public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i); }} public void release(int i) { level[i] = 0; Thread enters level L when it completes the loop

82 Claim Start at level L=0 At most n-L threads enter level L
© 2003 Herlihy and Shavit Claim Start at level L=0 At most n-L threads enter level L Corollary: mutual exclusion at level L=n-1 ncs L=0 L=1 L=n-2 cs L=n-1

83 Claim Start at level L=0 At most n-L threads enter level L
© 2003 Herlihy and Shavit Claim Start at level L=0 At most n-L threads enter level L Proof: by induction over L. ncs L=0 L=1 L=n-2 cs L=n-1

84 Induction Hypothesis No more than n-L+1 at level L-1
© 2003 Herlihy and Shavit Induction Hypothesis No more than n-L+1 at level L-1 Induction step: by contradiction Assume all at level L-1 enter level L A last to write victim[L] B is any other thread at level L ncs assume L-1 has n-L+1 L has n-L Why B exists: since L <= n-1, we have n-L+1 >= 2. We are going to show that assuming No more than n-L+1 at level L-1 we can prevent one more thread from getting in…SHOW DETAIL IN NEXT SLIDE cs prove

85 Proof Structure A B ncs Assumed to enter L-1 n-L+1 = 4 n-L+1 = 4
© 2003 Herlihy and Shavit Proof Structure ncs Assumed to enter L-1 A B n-L+1 = 4 n-L+1 = 4 Last to write victim[L] cs By way of contradiction all enter L We are going to show that assuming No more than n-L+1 at level L-1 we can prevent one more thread from getting in… Show that A must have seen B in level[L] and since victim[L] == A A could not have entered L

86 From the Code (1) writeB(level[B]=L)writeB(victim[L]=B)
© 2003 Herlihy and Shavit From the Code (1) writeB(level[B]=L)writeB(victim[L]=B) public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i) {}; }}

87 From the Code (2) writeA(victim[L]=A)readA(level[B])
© 2003 Herlihy and Shavit From the Code (2) writeA(victim[L]=A)readA(level[B]) public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i) {}; }}

88 By assumption, A is the last thread to write victim[L]
© 2003 Herlihy and Shavit By Assumption (3) writeB(victim[L]=B)writeA(victim[L]=A) By assumption, A is the last thread to write victim[L]

89 Combining Observations
© 2003 Herlihy and Shavit Combining Observations (1) writeB(level[B]=L)writeB(victim[L]=B) (3) writeB(victim[L]=B)writeA(victim[L]=A) (2) writeA(victim[L]=A)readA(level[B])

90 Combining Observations
© 2003 Herlihy and Shavit Combining Observations (1) writeB(level[B]=L)writeB(victim[L]=B) (3) writeB(victim[L]=B)writeA(victim[L]=A) (2) writeA(victim[L]=A)readA(level[B]) public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; while (($ k != i) level[k] >= L) && victim[L] == i) {}; }}

91 Combining Observations
© 2003 Herlihy and Shavit Combining Observations (1) writeB(level[B]=L)writeB(victim[L]=B) (3) writeB(victim[L]=B)writeA(victim[L]=A) (2) writeA(victim[L]=A)readA(level[B]) Thus, A read level[B] ≥ L, A was last to write victim[L], so it could not have entered level L!

92 The first thread entering level 1 the first thread entering CS
© 2003 Herlihy and Shavit No Starvation Filter Lock satisfies properties: Just like Peterson Alg at any level So no one starves But what about fairness? Threads can be overtaken by others Read textbook for detailed proof for starvation-freedom. The first thread entering level 1 may not be the first thread entering CS

93 Bounded Waiting Want stronger fairness guarantees
© 2003 Herlihy and Shavit Bounded Waiting Want stronger fairness guarantees Thread not “overtaken” too much Need to adjust definitions ….

94 Bounded Waiting Divide lock() method into 2 parts: Doorway interval:
© 2003 Herlihy and Shavit Bounded Waiting Divide lock() method into 2 parts: Doorway interval: Written as DA always finishes in finite steps Waiting interval: Written as WA may take unbounded steps It would be great if we could order threads by the order in which they performed the first step of the lock() method.

95 r-Bounded Waiting For threads A and B:
© 2003 Herlihy and Shavit r-Bounded Waiting For threads A and B: If DAk  DB j A’s k-th doorway precedes B’s j-th doorway Then CSAk  CSBj+r A’s k-th critical section precedes B’s (j+r)-th critical section B cannot overtake A by more than r times First-come-first-served means r = 0.

96 Fairness Again Filter Lock satisfies properties: No one starves
© 2003 Herlihy and Shavit Fairness Again Filter Lock satisfies properties: No one starves But very weak fairness Not r-bounded for any r! That’s pretty lame… How could it be that there is no lockout and yet there is no r such that the protocol is r-bounded? The answer is that for any given execution i there is some bound r_i, but not an r for all executions.

97 Bakery Algorithm Provides First-Come-First-Served How?
© 2003 Herlihy and Shavit Bakery Algorithm Provides First-Come-First-Served How? Take a “number” Wait until lower numbers have been served Lexicographic order (a,i) > (b,j) If a > b, or a = b and i > j

98 Bakery Algorithm class Bakery implements Lock { boolean[] flag;
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { boolean[] flag; Label[] label; public Bakery (int n) { flag = new boolean[n]; label = new Label[n]; for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } flag[A]: whether A wants to enter the critical section. label[A]: A’s number when entering the bakery

99 Bakery Algorithm CS n-1 class Bakery implements Lock { boolean[] flag;
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { boolean[] flag; Label[] label; public Bakery (int n) { flag = new boolean[n]; label = new Label[n]; for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } n-1 f t 2 5 4 6 CS flag[A]: whether A wants to enter the critical section. label[A]: A’s number when entering the bakery

100 Bakery Algorithm class Bakery implements Lock { … public void lock() {
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); }

101 Bakery Algorithm Doorway class Bakery implements Lock { …
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Doorway

102 Bakery Algorithm I’m interested class Bakery implements Lock { …
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } I’m interested

103 Take increasing label (read labels in some arbitrary order)
© 2003 Herlihy and Shavit Bakery Algorithm Take increasing label (read labels in some arbitrary order) class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); }

104 Bakery Algorithm Someone is interested class Bakery implements Lock {
© 2003 Herlihy and Shavit Bakery Algorithm Someone is interested class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); }

105 With lower (label,i) in lexicographic order
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { boolean flag[n]; int label[n]; public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Someone is interested With lower (label,i) in lexicographic order

106 Bakery Algorithm class Bakery implements Lock { …
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { public void unlock() { flag[i] = false; }

107 Bakery Algorithm No longer interested labels are always increasing
© 2003 Herlihy and Shavit Bakery Algorithm class Bakery implements Lock { public void unlock() { flag[i] = false; } No longer interested labels are always increasing

108 No Deadlock There is always one thread i with smallest (label[i], i)
© 2003 Herlihy and Shavit No Deadlock There is always one thread i with smallest (label[i], i) Ties are impossible (why?)

109 First-Come-First-Served
© 2003 Herlihy and Shavit First-Come-First-Served If DA  DBthen A’s label is smaller And: writeA(label[A])  readB(label[A])  writeB(label[B])  readB(flag[A]) So B is locked out while flag[A] is true class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } If DA  DBthen A’s label is earlier. By the code B reads A’s label, then writes its own, then checks A’s label and compares to its own. Moreover, A writes its label before B can read it, so A has an earlier (lower) label, and B will see it and not go in.

110 Mutual Exclusion Suppose A and B in CS together
© 2003 Herlihy and Shavit Mutual Exclusion Suppose A and B in CS together Suppose A has smaller (label[A], A) When B entered, it must have seen flag[A] is false, or (label[A], A) > (label[B], B) class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); }

111 Mutual Exclusion By assumption so B must have seen flag[A] == false
© 2003 Herlihy and Shavit Mutual Exclusion By assumption so B must have seen flag[A] == false LabelingB  readB(flag[A])  writeA(flag[A])  LabelingA So label[A] > label[B] Which contradicts the assumption class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); }

112 Bakery Y232K Bug class Bakery implements Lock { … public void lock() {
© 2003 Herlihy and Shavit Bakery Y232K Bug class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Y2K: 千年虫问题,年份只使用两位十进制数来表示,因此当系统进行跨世纪的日期处理运 算时就会出现错误的结果

113 Mutex breaks if label[i] overflows
© 2003 Herlihy and Shavit Bakery Y232K Bug Mutex breaks if label[i] overflows class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); }

114 Does Overflow Actually Matter?
© 2003 Herlihy and Shavit Does Overflow Actually Matter? Yes Y2K 18 January 2038 (Unix time_t rollover) 16-bit counters No 64-bit counters Maybe 32-bit counters

115 Timestamps Label variable is really a timestamp Need ability to
© 2003 Herlihy and Shavit Timestamps Label variable is really a timestamp Need ability to Read others’ timestamps Compare them Generate a later timestamp Can we do this without overflow?

116 The Good News One can construct a Wait-free (no mutual exclusion)
© 2003 Herlihy and Shavit The Good News One can construct a Wait-free (no mutual exclusion) Concurrent Timestamping system That never overflows

117 The Good News Bad This part is hard One can construct a
© 2003 Herlihy and Shavit The Good News Bad One can construct a Wait-free (no mutual exclusion) Concurrent Timestamping system That never overflows This part is hard

118 Instead … We construct a Sequential timestamping system
© 2003 Herlihy and Shavit Instead … We construct a Sequential timestamping system Same basic idea But simpler Uses mutex to read & write atomically No good for building locks But useful anyway Scan-and-label as a whole is atomic

119 Precedence Graphs 1 2 3 Timestamps form directed graph Edge x to y
© 2003 Herlihy and Shavit Precedence Graphs 1 2 3 Timestamps form directed graph Edge x to y Means x is later timestamp We say x dominates y 假设每个线程有一个token。assigning a timestamp to thread A就是place A’s token on the timestamp’s node.

120 Unbounded Counter Precedence Graph
© 2003 Herlihy and Shavit Unbounded Counter Precedence Graph 1 2 3 Timestamping = move tokens on graph Atomically read others’ tokens move mine

121 Unbounded Counter Precedence Graph
© 2003 Herlihy and Shavit Unbounded Counter Precedence Graph 1 2 3

122 Unbounded Counter Precedence Graph
© 2003 Herlihy and Shavit Unbounded Counter Precedence Graph 1 2 3 假设只有2个线程 takes 0 takes 1 takes 2

123 Two-Thread Bounded Precedence Graph
© 2003 Herlihy and Shavit Two-Thread Bounded Precedence Graph 1 2

124 Two-Thread Bounded Precedence Graph
© 2003 Herlihy and Shavit Two-Thread Bounded Precedence Graph 1 2

125 Two-Thread Bounded Precedence Graph
© 2003 Herlihy and Shavit Two-Thread Bounded Precedence Graph 1 2

126 Two-Thread Bounded Precedence Graph
© 2003 Herlihy and Shavit Two-Thread Bounded Precedence Graph 1 2

127 Two-Thread Bounded Precedence Graph T2
© 2003 Herlihy and Shavit Two-Thread Bounded Precedence Graph T2 and so on … 1 2

128 Three-Thread Bounded Precedence Graph?
© 2003 Herlihy and Shavit Three-Thread Bounded Precedence Graph? 1 3 2

129 Three-Thread Bounded Precedence Graph?
© 2003 Herlihy and Shavit Three-Thread Bounded Precedence Graph? 1 Not clear what to do if one thread gets stuck 3 2

130 Replace each vertex with a copy of the graph
© 2003 Herlihy and Shavit Graph Composition 1 2 1 2 T3=T2*T2 Replace each vertex with a copy of the graph

131 Three-Thread Bounded Precedence Graph T3
© 2003 Herlihy and Shavit Three-Thread Bounded Precedence Graph T3 2 1

132 Three-Thread Bounded Precedence Graph T3
© 2003 Herlihy and Shavit Three-Thread Bounded Precedence Graph T3 2 1 20 < 02 < 12

133 Three-Thread Bounded Precedence Graph T3
© 2003 Herlihy and Shavit Three-Thread Bounded Precedence Graph T3 1 2 2 1 and so on…

134 In General Tk = T2 * Tk-1 label size = Log2(3k-1) < 2k
© 2003 Herlihy and Shavit In General label size = Log2(3k-1) < 2k Tk = T2 * Tk-1 K threads need 3k-1 nodes G * H: G的每个节点换成一个图H。 Label size: 在计算机中存储这样的Label需要多少bit

135 Deep Philosophical Question
© 2003 Herlihy and Shavit Deep Philosophical Question The Bakery Algorithm is Succinct, Elegant, and Fair. Q: So why isn’t it practical? A: Well, you have to read N distinct variables Q: Clever lock avoiding this overhead? 简洁、优雅、公平. N:the maximum number of concurrent threads. Is there a clever lock algorithm based on reading and writing memory that avoids this overhead? NO.

136 © 2003 Herlihy and Shavit Shared Memory Shared read/write memory locations called Registers (historical reasons) Come in different flavors Multi-Reader-Single-Writer (Flag[]) Multi-Reader-Multi-Writer (Victim[]) Not that interesting: SRMW and SRSW

137 © 2003 Herlihy and Shavit Theorem At least N MRSW (multi-reader/single-writer) registers are needed to solve deadlock-free mutual exclusion. N registers like Flag[]… This proof is not easy for undergraduates but you need to do it so that they see the weakness of read-write registers due to the fact that when they write they obliterate traces of what other threads wrote.

138 Proving Algorithmic Impossibility
© 2003 Herlihy and Shavit Proving Algorithmic Impossibility C To show no algorithm exists: assume by way of contradiction one does, show a bad execution that violates properties: in our case assume an alg for deadlock free mutual exclusion using < N registers write CS Explain the notion of a proof that NO ALG EXISTS by showing a bad execution.

139 Proof: Need N-MRSW Registers
© 2003 Herlihy and Shavit Proof: Need N-MRSW Registers Each thread must write to some register A B C write write CS CS CS Bad execution has one thread go in, then at least one of the others must be able to get in since the algorithm must provide deadlock free mutual exclusion …can’t tell whether A is in critical section

140 Upper Bound Bakery algorithm So the bound is (pretty) tight
© 2003 Herlihy and Shavit Upper Bound Bakery algorithm Uses 2N MRSW registers So the bound is (pretty) tight But what if we use MRMW registers? Like victim[] ?

141 © 2003 Herlihy and Shavit Bad News Theorem At least N MRMW multi-reader/multi-writer registers are needed to solve deadlock-free mutual exclusion. (So multiple writers don’t help)

142 Theorem (First 2-Threads)
© 2003 Herlihy and Shavit Theorem (First 2-Threads) Theorem: Deadlock-free mutual exclusion for 2 threads requires at least 2 multi-reader multi-writer registers Proof: assume one register suffices and derive a contradiction Show proof for two threads first so students get the general structure of the proof. Without this they will have a hard time to get the details of the three thread case.

143 Two Thread Execution R Threads run, reading and writing R
© 2003 Herlihy and Shavit Two Thread Execution A B R Write(R) CS CS Threads run, reading and writing R Deadlock free so at least one gets in

144 Covering State for One Register Always Exists
© 2003 Herlihy and Shavit Covering State for One Register Always Exists B Write(R) In any protocol B has to write to the register before entering CS, so stop it just before In any protocol, we run B never letting it write the register, we stop B when B’s next step is a write. Covering state: at least one thread is about to write, but the state looks like the critical section is empty

145 A runs, possibly writes to the register, enters CS
© 2003 Herlihy and Shavit Proof: Assume Cover of 1 A B Write(R) A runs, possibly writes to the register, enters CS CS

146 Proof: Assume Cover of 1 A B B Runs, first obliterating
© 2003 Herlihy and Shavit Proof: Assume Cover of 1 A B B Runs, first obliterating any trace of A, then also enters the critical section Write(R) Obliterate: 擦去 CS CS

147 © 2003 Herlihy and Shavit Theorem Deadlock-free mutual exclusion for 3 threads requires at least 3 multi-reader multi-writer registers

148 Proof: Assume Cover of 2 A B C Only 2 registers Write(RB) Write(RC)
© 2003 Herlihy and Shavit Proof: Assume Cover of 2 A B C Write(RB) Write(RC) 设此时B和C分别cover R_B和R_C。 we will show how to derive a cover of the two registers later… Only 2 registers

149 Writes to one or both registers, enters CS
© 2003 Herlihy and Shavit Run A Solo A B C Write(RB) Write(RC) Writes to one or both registers, enters CS CS

150 Other threads obliterate evidence that A entered CS
© 2003 Herlihy and Shavit Obliterate Traces of A A B C Write(RB) Write(RC) 令B和C分别write to their covered locations. Other threads obliterate evidence that A entered CS CS

151 Mutual Exclusion Fails
© 2003 Herlihy and Shavit Mutual Exclusion Fails A B C Write(RB) Write(RC) CS looks empty, so another thread gets in CS CS

152 © 2003 Herlihy and Shavit Proof Strategy Proved: a contradiction starting from a covering state for 2 registers Claim: a covering state for 2 registers is reachable from any state where CS is empty

153 Covering State for Two A B If we run B through CS 3 times, B must
© 2003 Herlihy and Shavit Covering State for Two A B Write(RA) Write(RB) This is based on pigeon-hole principle, and its not a specific register, just some register. Once the register is determined, we can call that register R_B. If we run B through CS 3 times, B must return twice to cover some register, say RB

154 Covering State for Two A B Write(RA) Write(RB)
© 2003 Herlihy and Shavit Covering State for Two A B Write(RA) Write(RB) Start with B covering register RB for the 1st time Run A until it is about to write to uncovered RA Are we done?

155 Covering State for Two NO! A could have written to RB
© 2003 Herlihy and Shavit Covering State for Two A B Write(RA) Write(RB) NO! A could have written to RB So CS no longer looks empty Notice that the problem is the third thread C that can see what is written in these registers and not get in, this is why we need to have both registers be in a state consistent with no-one being in the critical section.

156 Covering State for Two A B Run B obliterating traces of A in RB
© 2003 Herlihy and Shavit Covering State for Two A B Write(RA) Write(RB) Run B obliterating traces of A in RB Run B again until it is about to write to RB Now we are done

157 Inductively We Can Show
© 2003 Herlihy and Shavit Inductively We Can Show A B C Write(RA) Write(RB) Write(RC) There is a covering state Where k threads not in CS cover k distinct registers Proof follows when k = N-1

158 © 2003 Herlihy and Shavit Summary of Lecture In the 1960’s many incorrect solutions to starvation-free mutual exclusion using RW-registers were published… Today we know how to solve FIFO N thread mutual exclusion using 2N RW-Registers

159 Summary of Lecture N RW-Registers inefficient
© 2003 Herlihy and Shavit Summary of Lecture N RW-Registers inefficient Because writes “cover” older writes Need stronger hardware operations that do not have the “covering problem” In next lectures - understand what these operations are… Say that the issue that writes “cover” older writes is a fundamental problem with RW-registers that shows up everywhere…

160           This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
© 2003 Herlihy and Shavit You are free: to Share — to copy, distribute and transmit the work to Remix — to adapt the work Under the following conditions: Attribution. You must attribute the work to “The Art of Multiprocessor Programming” (but not in any way that suggests that the authors endorse you or your use of the work). Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to Any of the above conditions can be waived if you get permission from the copyright holder. Nothing in this license impairs or restricts the author's moral rights.


Download ppt "Mutual Exclusion Modified from Companion slides for"

Similar presentations


Ads by Google