Presentation is loading. Please wait.

Presentation is loading. Please wait.

Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.

Similar presentations


Presentation on theme: "Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit."— Presentation transcript:

1 Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

2 Art of Multiprocessor Programming 2 Review: Amdahl's Law Speedup =

3 Shared Data Structures 75% Unshared 25% Shared Coarse Grained Fine Grained Why fine-grained parallelism maters 75% Unshared 25% Shared Honk!

4 Example Synchronization Paradigms Mutual exclusion Readers-Writers Producer-Consumer Art of Multiprocessor Programming 4

5 5 Mutual Exclusion We will clarify our understanding of mutual exclusion We will also show you how to reason about various properties in an asynchronous concurrent setting

6 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." Art of Multiprocessor Programming 6

7 7 Mutual Exclusion Formal problem definitions Solutions for 2 threads Solutions for n threads Fair solutions Inherent costs

8 Art of Multiprocessor Programming 8 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

9 Art of Multiprocessor Programming 9 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

10 Art of Multiprocessor Programming 10 “Absolute, true and mathematical time, of itself and from its own nature, flows equably without relation to anything external.” (Isaac Newton, 1689) “Time is what keeps everything from happening at once.” (Ray Cummings, 1922) Time time

11 Art of Multiprocessor Programming 11 time An event a 0 of thread A is –Instantaneous –No simultaneous events (break ties) a0a0 Events

12 Art of Multiprocessor Programming 12 time A thread A is (formally) a sequence a 0, a 1,... of events –“Trace” model –Notation: a 0  a 1 indicates order a0a0 Threads a1a1 a2a2 …

13 Art of Multiprocessor Programming 13 Assign to shared variable Assign to local variable Invoke method Return from method Lots of other things … Example Thread Events

14 Art of Multiprocessor Programming 14 Threads are State Machines Events are transitions a0a0 a1a1 a2a2 a3a3

15 Art of Multiprocessor Programming 15 States Thread State –Program counter –Local variables System state –Object fields (shared variables) –Union of thread states

16 Art of Multiprocessor Programming 16 time Thread A Concurrency

17 Art of Multiprocessor Programming 17 time Thread A Thread B Concurrency

18 Art of Multiprocessor Programming 18 time Interleavings Events of two or more threads –Interleaved –Not necessarily independent (why?)

19 Art of Multiprocessor Programming 19 time An interval A 0 =(a 0,a 1 ) is –Time between events a 0 and a 1 a0a0 a1a1 Intervals A0A0

20 Art of Multiprocessor Programming 20 time Intervals may Overlap a0a0 a1a1 A0A0 b0b0 b1b1 B0B0

21 Art of Multiprocessor Programming 21 time Intervals may be Disjoint a0a0 a1a1 A0A0 b0b0 b1b1 B0B0

22 Art of Multiprocessor Programming 22 time Precedence a0a0 a1a1 A0A0 b0b0 b1b1 B0B0 Interval A 0 precedes interval B 0

23 Art of Multiprocessor Programming 23 Precedence Notation: A 0  B 0 Formally, –End event of A 0 before start event of B 0 –Also called “happens before” or “precedes”

24 Art of Multiprocessor Programming 24 Precedence Ordering Remark: A 0  B 0 is just like saying –1066 AD  1492 AD, –Middle Ages  Renaissance, Oh wait, –what about this week vs this month?

25 Art of Multiprocessor Programming 25 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!

26 Art of Multiprocessor Programming 26 Partial Orders (review) 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

27 Art of Multiprocessor Programming 27 Total Orders (review) Also –Irreflexive –Antisymmetric –Transitive Except that for every distinct A, B, –Either A   B or B   A

28 Art of Multiprocessor Programming 28 Repeated Events while (mumble) { a 0 ; a 1 ; } a0ka0k k-th occurrence of event a 0 A0kA0k k-th occurrence of interval A 0 =(a 0,a 1 )

29 Art of Multiprocessor Programming 29 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

30 Art of Multiprocessor Programming 30 Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); }

31 Art of Multiprocessor Programming 31 Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } acquire lock

32 Art of Multiprocessor Programming 32 Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } release lock acquire lock

33 Art of Multiprocessor Programming 33 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; }}

34 Art of Multiprocessor Programming 34 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

35 Art of Multiprocessor Programming 35 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)

36 Art of Multiprocessor Programming 36 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

37 Art of Multiprocessor Programming 37 Mutual Exclusion Let CS i k be thread i's k-th critical section execution

38 Art of Multiprocessor Programming 38 Mutual Exclusion Let CS i k be thread i's k-th critical section execution And CS j m be thread j's m-th critical section execution

39 Art of Multiprocessor Programming 39 Mutual Exclusion Let CS i k be thread i's k-th critical section execution And CS j m be j's m-th execution Then either – or

40 Art of Multiprocessor Programming 40 Mutual Exclusion Let CS i k be thread i's k-th critical section execution And CS j m be j's m-th execution Then either – or CS i k  CS j m

41 Art of Multiprocessor Programming 41 Mutual Exclusion Let CS i k be thread i's k-th critical section execution And CS j m be j's m-th execution Then either – or CS i k  CS j m CS j m  CS i k

42 Art of Multiprocessor Programming 42 Deadlock-Free 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

43 Art of Multiprocessor Programming 43 Starvation-Free If some thread calls lock() –It will eventually return Individual threads make progress

44 Art of Multiprocessor Programming 44 Two-Thread vs n-Thread Solutions 2-thread solutions first –Illustrate most basic ideas –Fits on one slide Then n-thread solutions

45 Art of Multiprocessor Programming 45 class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; … } Two-Thread Conventions

46 Art of Multiprocessor Programming 46 class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; … } Two-Thread Conventions Henceforth: i is current thread, j is other thread

47 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} }

48 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Each thread has flag

49 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Set my flag

50 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Wait for other flag to become false

51 Art of Multiprocessor Programming 51 Assume CS A j overlaps CS B k Consider each thread's last –(j th and k th ) read and write … –in lock() before entering Derive a contradiction LockOne Satisfies Mutual Exclusion

52 Art of Multiprocessor Programming 52 write A (flag[A]=true)  read A (flag[B]==false)  CS A write B (flag[B]=true)  read B (flag[A]==false)  CS B From the Code class LockOne implements Lock { … public void lock() { flag[i] = true; while (flag[j]) {} }

53 Art of Multiprocessor Programming 53 read A (flag[B]==false)  write B (flag[B]=true) read B (flag[A]==false)  write A (flag[A]=true) From the Assumption

54 Art of Multiprocessor Programming 54 Assumptions: –read A (flag[B]==false)  write B (flag[B]=true) –read B (flag[A]==false)  write A (flag[A]=true) From the code –write A (flag[A]=true)  read A (flag[B]==false) –write B (flag[B]=true)  read B (flag[A]==false) Combining

55 Art of Multiprocessor Programming 55 Assumptions: –read A (flag[B]==false)  write B (flag[B]=true) –read B (flag[A]==false)  write A (flag[A]=true) From the code –write A (flag[A]=true)  read A (flag[B]==false) –write B (flag[B]=true)  read B (flag[A]==false) Combining

56 Art of Multiprocessor Programming 56 Assumptions: –read A (flag[B]==false)  write B (flag[B]=true) –read B (flag[A]==false)  write A (flag[A]=true) From the code –write A (flag[A]=true)  read A (flag[B]==false) –write B (flag[B]=true)  read B (flag[A]==false) Combining

57 Art of Multiprocessor Programming 57 Assumptions: –read A (flag[B]==false)  write B (flag[B]=true) –read B (flag[A]==false)  write A (flag[A]=true) From the code –write A (flag[A]=true)  read A (flag[B]==false) –write B (flag[B]=true)  read B (flag[A]==false) Combining

58 Art of Multiprocessor Programming 58 Assumptions: –read A (flag[B]==false)  write B (flag[B]=true) –read B (flag[A]==false)  write A (flag[A]=true) From the code –write A (flag[A]=true)  read A (flag[B]==false) –write B (flag[B]=true)  read B (flag[A]==false) Combining

59 Art of Multiprocessor Programming 59 Assumptions: –read A (flag[B]==false)  write B (flag[B]=true) –read B (flag[A]==false)  write A (flag[A]=true) From the code –write A (flag[A]=true)  read A (flag[B]==false) –write B (flag[B]=true)  read B (flag[A]==false) Combining

60 Art of Multiprocessor Programming 60 Cycle! Impossible in a partial order

61 Art of Multiprocessor Programming 61 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]){}

62 Art of Multiprocessor Programming 62 LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} }

63 Art of Multiprocessor Programming 63 LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} } Let other go first

64 Art of Multiprocessor Programming 64 LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} } Wait for permission

65 Art of Multiprocessor Programming 65 LockTwo public class Lock2 implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} } Nothing to do

66 Art of Multiprocessor Programming 66 public void LockTwo() { victim = i; while (victim == i) {}; } 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

67 Art of Multiprocessor Programming 67 Peterson's Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; }

68 Art of Multiprocessor Programming 68 Peterson's Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Announce I'm interested

69 Art of Multiprocessor Programming 69 Peterson's Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Announce I'm interested Defer to other

70 Art of Multiprocessor Programming 70 Peterson's Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Announce I'm interested Defer to other Wait while other interested & I'm the victim

71 Art of Multiprocessor Programming 71 Peterson's Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } No longer interested Announce I'm interested Defer to other Wait while other interested & I'm the victim

72 Art of Multiprocessor Programming 72 Mutual Exclusion (1) write B (Flag[B]=true)  write B (victim=B) public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } From the Code

73 Art of Multiprocessor Programming 73 Also from the Code (2) write A (victim=A)  read A (flag[B])  read A (victim) public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; }

74 Art of Multiprocessor Programming 74 Assumption W.L.O.G. assume A is the last thread to write victim (3) write B (victim=B)  write A (victim=A)

75 Art of Multiprocessor Programming 75 Combining Observations (1) write B (flag[B]=true)  write B (victim=B) (3) write B (victim=B)  write A (victim=A) (2) write A (victim=A)  read A (flag[B])  read A (victim)

76 Art of Multiprocessor Programming 76 Combining Observations (1) write B (flag[B]=true)  write B (victim=B) (3) write B (victim=B)  write A (victim=A) (2) write A (victim=A)  read A (flag[B])  read A (victim)

77 Art of Multiprocessor Programming 77 Combining Observations (1) write B (flag[B]=true)  write B (victim=B) (3) write B (victim=B)  write A (victim=A) (2) write A (victim=A)  read A (flag[B])  read A (victim) A read flag[B] == true and victim == A, so it could not have entered the CS (QED)

78 Art of Multiprocessor Programming 78 Deadlock Free Thread blocked –only at while loop –only if other's flag is true –only if it is the victim Solo: other's flag is false Both: one or the other not the victim public void lock() { … while (flag[j] && victim == i) {};

79 Art of Multiprocessor Programming 79 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; }

80 Art of Multiprocessor Programming 80 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

81 Art of Multiprocessor Programming 81 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; }} … } level victim n -1 0 1 0000004 2 2 Thread 2 at level 4 0 4

82 Art of Multiprocessor Programming 82 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; }}

83 Art of Multiprocessor Programming 83 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 release(int i) { level[i] = 0; }} Filter One level at a time

84 Art of Multiprocessor Programming 84 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 release(int i) { level[i] = 0; }} Filter Announce intention to enter level L

85 Art of Multiprocessor Programming 85 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; }} Filter Give priority to anyone but me

86 Art of Multiprocessor Programming 86 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; }} Filter Wait as long as someone else is at same or higher level, and I'm designated victim

87 Art of Multiprocessor Programming 87 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; }} Filter Thread enters level L when it completes the loop

88 Art of Multiprocessor Programming 88 Claim Start at level L=0 At most n-L threads enter level L Mutual exclusion at level L=n-1 ncs csL=n-1 L=1 L=n-2 L=0

89 Art of Multiprocessor Programming 89 Induction Hypothesis Assume all at level L-1 enter level L A last to write victim[L] B is any other thread at level L No more than n-(L-1) at level L-1 Induction step: by contradiction ncs cs L-1 has n-(L-1) L has n-L assume prove

90 Art of Multiprocessor Programming 90 Proof Structure ncs cs Assumed to enter L-1 By way of contradiction all enter L n-(L-1) = 4 A B Last to write victim[L] Show that A must have seen B in level[L] and since victim[L] == A could not have entered

91 Art of Multiprocessor Programming 91 Just Like Peterson (1) write B (level[B]=L)  write B (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) {}; }} From the Code

92 Art of Multiprocessor Programming 92 From the Code (2) write A (victim[L]=A)  read A (level[B])  read A (victim[L]) 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) {}; }}

93 Art of Multiprocessor Programming 93 By Assumption By assumption, A is the last thread to write victim[L] (3) write B (victim[L]=B)  write A (victim[L]=A)

94 Art of Multiprocessor Programming 94 Combining Observations (1) write B (level[B]=L)  write B (victim[L]=B) (3) write B (victim[L]=B)  write A (victim[L]=A) (2) write A (victim[L]=A)  read A (level[B])  read A (victim[L])

95 Art of Multiprocessor Programming 95 Combining Observations (1) write B (level[B]=L)  write B (victim[L]=B) (3) write B (victim[L]=B)  write A (victim[L]=A) (2) write A (victim[L]=A)  read A (level[B])  read A (victim[L])

96 Art of Multiprocessor Programming 96 Combining Observations (1) write B (level[B]=L)  write B (victim[L]=B) (3) write B (victim[L]=B)  write A (victim[L]=A) (2) write A (victim[L]=A)  read A (level[B])  read A (victim[L]) A read level[B] ≥ L, and victim[L] = A, so it could not have entered level L!

97 Art of Multiprocessor Programming 97 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

98 Art of Multiprocessor Programming 98 Bounded Waiting Want stronger fairness guarantees Thread not “overtaken” too much If A starts before B, then A enters before B? But what does “start” mean? Need to adjust definitions ….

99 Art of Multiprocessor Programming 99 Bounded Waiting Divide lock() method into 2 parts: –Doorway interval: Written D A always finishes in finite steps –Waiting interval: Written W A may take unbounded steps

100 Art of Multiprocessor Programming 100 For threads A and B: –If D A k  D B j A's k-th doorway precedes B's j-th doorway –Then CS A k  CS B j+r A's k-th critical section precedes B's j+r-th critical section B cannot overtake A more than r times First-come-first-served  r = 0 r-Bounded Waiting

101 Art of Multiprocessor Programming 101 What is “r” for Peterson's Algorithm? public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Answer: r = 0

102 Art of Multiprocessor Programming 102 What is “r” for the Filter Algorithm? 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; }} Answer: there is no value of “r”

103 Art of Multiprocessor Programming 103 For threads A and B: –If D A k  D B j A's k-th doorway precedes B's j-th doorway –Then CS A k  CS B j A's k-th critical section precedes B's j-th critical section B cannot overtake A First-Come-First-Served

104 Art of Multiprocessor Programming 104 Fairness Filter Lock satisfies properties: –No one starves –But very weak fairness Can be overtaken arbitrary # of times –So being fair is stronger than avoiding starvation –And filter is pretty lame…

105 Art of Multiprocessor Programming 105 Bakery Algorithm Provides First-Come-First-Served for n threads 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

106 Art of Multiprocessor Programming 106 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; } …

107 Art of Multiprocessor Programming 107 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 0 fffftft 2 f 0000504 0 6 CS

108 Art of Multiprocessor Programming 108 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)); }

109 Art of Multiprocessor Programming 109 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

110 Art of Multiprocessor Programming 110 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

111 Art of Multiprocessor Programming 111 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)); } Take increasing label (read labels in some arbitrary order)

112 Art of Multiprocessor Programming 112 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)); } Someone is interested

113 Art of Multiprocessor Programming 113 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 … … whose (label,i) in lexicographic order is lower

114 Art of Multiprocessor Programming 114 Bakery Algorithm class Bakery implements Lock { … public void unlock() { flag[i] = false; }

115 Art of Multiprocessor Programming 115 Bakery Algorithm class Bakery implements Lock { … public void unlock() { flag[i] = false; } No longer interested labels are always increasing

116 Art of Multiprocessor Programming 116 No Deadlock There is always one thread with earliest label Ties are impossible (why?)

117 Art of Multiprocessor Programming 117 First-Come-First-Served If D A  D B then –A's label is smaller And: – write A (label[A])  – read B (label[A])  –write B (label[B])  read B (flag[A]) So B sees –smaller label for A – 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)); }

118 Art of Multiprocessor Programming 118 Mutual Exclusion Suppose A and B in CS together Suppose A has earlier label When B entered, it must have seen –flag[A] is false, or –label[A] > label[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)); }

119 Art of Multiprocessor Programming 119 Mutual Exclusion Labels are strictly increasing so B must have seen flag[A] == false

120 Art of Multiprocessor Programming 120 Mutual Exclusion Labels are strictly increasing so B must have seen flag[A] == false Labeling B  read B (flag[A])  write A (flag[A])  Labeling A

121 Art of Multiprocessor Programming 121 Mutual Exclusion Labels are strictly increasing so B must have seen flag[A] == false Labeling B  read B (flag[A])  write A (flag[A])  Labeling A Which contradicts the assumption that A has an earlier label

122 Art of Multiprocessor Programming 122 Bakery Y2 32 K 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)); }

123 Art of Multiprocessor Programming 123 Bakery Y2 32 K 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)); } Mutex breaks if label[i] overflows

124 Art of Multiprocessor Programming 124 Does Overflow Actually Matter? Yes –Y2K –18 January 2038 (Unix time_t rollover) –16-bit counters No –64-bit counters Maybe –32-bit counters

125 Art of Multiprocessor Programming 125 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?

126 Art of Multiprocessor Programming 126 One can construct a –Wait-free (no mutual exclusion) –Concurrent –Timestamping system –That never overflows The Good News

127 Art of Multiprocessor Programming 127 One can construct a –Wait-free (no mutual exclusion) –Concurrent –Timestamping system –That never overflows The Good News This part is hard Bad

128 Art of Multiprocessor Programming 128 Instead … We construct a Sequential timestamping system –Same basic idea –But simpler As if we use mutex to read & write atomically No good for building locks –But useful anyway

129 Art of Multiprocessor Programming 129 Precedence Graphs 0123 Timestamps form directed graph Edge x to y –Means x is later timestamp –We say x dominates y

130 Art of Multiprocessor Programming 130 Unbounded Counter Precedence Graph 0123 Timestamping = move tokens on graph Atomically –read others' tokens –move mine Ignore tie-breaking for now

131 Art of Multiprocessor Programming 131 Unbounded Counter Precedence Graph 0123

132 Art of Multiprocessor Programming 132 Unbounded Counter Precedence Graph 0123 takes 0 takes 1 takes 2

133 Art of Multiprocessor Programming 133 Two-Thread Bounded Precedence Graph 0 12

134 Art of Multiprocessor Programming 134 Two-Thread Bounded Precedence Graph 0 12

135 Art of Multiprocessor Programming 135 Two-Thread Bounded Precedence Graph 0 12

136 Art of Multiprocessor Programming 136 Two-Thread Bounded Precedence Graph 0 12

137 Art of Multiprocessor Programming 137 Two-Thread Bounded Precedence Graph T 2 0 12 and so on …

138 Art of Multiprocessor Programming 138 Three-Thread Bounded Precedence Graph? 1203

139 Art of Multiprocessor Programming 139 Three-Thread Bounded Precedence Graph? 1203 What to do if one thread gets stuck?

140 Art of Multiprocessor Programming 140 Graph Composition 0 12 0 12 Replace each vertex with a copy of the graph T 3 =T 2 *T 2

141 Art of Multiprocessor Programming 141 Three-Thread Bounded Precedence Graph T 3 2 0 12 1 0 12 0 0 12

142 Art of Multiprocessor Programming 142 Three-Thread Bounded Precedence Graph T 3 2 0 12 1 0 12 0 0 12 200212 <<

143 Art of Multiprocessor Programming 143 Three-Thread Bounded Precedence Graph T 3 2 0 12 1 0 12 0 0 12 and so on…

144 Art of Multiprocessor Programming 144 In General T k = T 2 * T k-1 K threads need 3 k nodes label size = Log 2 (3 k ) = 2k

145 Art of Multiprocessor Programming 145 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

146 Art of Multiprocessor Programming 146 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

147 Art of Multiprocessor Programming 147 Theorem At least N MRSW (multi-reader/single- writer) registers are needed to solve deadlock-free mutual exclusion. N registers such as flag[] …

148 Art of Multiprocessor Programming 148 Proving Algorithmic Impossibility CS write 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

149 Art of Multiprocessor Programming 149 Proof: Need N-MRSW Registers Each thread must write to some register …can't tell whether A is in critical section write CS write A B C

150 Art of Multiprocessor Programming 150 Upper Bound Bakery algorithm –Uses 2N MRSW registers So the bound is (pretty) tight But what if we use MRMW registers? –Like victim[] ?

151 Art of Multiprocessor Programming 151 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)

152 Art of Multiprocessor Programming 152 Theorem (For 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

153 Art of Multiprocessor Programming 153 Two Thread Execution Threads run, reading and writing R Deadlock free so at least one gets in B A CS Write(R) CS R

154 Art of Multiprocessor Programming 154 Covering State for One Register Always Exists Write(R) B In any protocol B has to write to the register before entering CS, so stop it just before

155 Art of Multiprocessor Programming 155 Proof: Assume Cover of 1 A B Write(R) CS A runs, possibly writes to the register, enters CS

156 Art of Multiprocessor Programming 156 Proof: Assume Cover of 1 A B CS B Runs, first obliterating any trace of A, then also enters the critical section Write(R) CS

157 Art of Multiprocessor Programming 157 Theorem Deadlock-free mutual exclusion for 3 threads requires at least 3 multi-reader multi-writer registers

158 Art of Multiprocessor Programming 158 Theorem Deadlock-free mutual exclusion for n threads requires at least n multi-reader multi-writer registers

159 Art of Multiprocessor Programming 159 Proof: Assume Cover of 2 Write(R B ) B Write(R C ) C A Only 2 registers

160 Art of Multiprocessor Programming 160 Run A Solo Write(R B ) B Write(R C ) C A Writes to one or both registers, enters CS CS

161 Art of Multiprocessor Programming 161 Obliterate Traces of A Write(R B ) B Write(R C ) C A Other threads obliterate evidence that A entered CS CS

162 Art of Multiprocessor Programming 162 Mutual Exclusion Fails Write(R B ) B Write(R C ) C A CS CS looks empty, so another thread gets in

163 Art of Multiprocessor Programming 163 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

164 Art of Multiprocessor Programming 164 If we run B through CS 3 times, B must return twice to cover some register, say R B Covering State for Two Write(R B ) B Write(R A ) A

165 Art of Multiprocessor Programming 165 Covering State for Two Start with B covering register R B for the 1 st time Run A until it is about to write to uncovered R A Are we done? Write(R B ) B Write(R A ) A

166 Art of Multiprocessor Programming 166 Covering State for Two NO! A could have written to R B So CS no longer looks empty to thread C Write(R B ) B Write(R A ) A

167 Art of Multiprocessor Programming 167 Covering State for Two Run B obliterating traces of A in R B Run B again until it is about to write to R B Now we are done Write(R B ) B Write(R A ) A

168 Art of Multiprocessor Programming 168 Inductively We Can Show There is a covering state –Where k threads not in CS cover k distinct registers –Proof follows when k = N-1 Write(R B ) B Write(R C ) C Write(R A ) A

169 Art of Multiprocessor Programming 169 Summary of Lecture In the 1960's several 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

170 Art of Multiprocessor Programming 170 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…

171 Art of Multiprocessor Programming 171 This work is licensed under a Creative Commons Attribution- ShareAlike 2.5 License.Creative Commons Attribution- ShareAlike 2.5 License 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 –http://creativecommons.org/licenses/by-sa/3.0/. 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 Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit."

Similar presentations


Ads by Google