Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS 640, Spring 2009 University of pennsylvania Prisoners and a switch puzzle (Distributed coordination) • At the start, prisoners get together and decide a strategy, but later have no communication • Warden’s office has a switch (on/off) • Warden repeatedly picks a prisoner, and brings him to office • Prisoner can declare “all have visited the office at least once”, may toggle the switch, or leave it unchanged. Then warden takes prisoner back to his cell Art of Multiprocessor Programming 2 Prisoners and a switch puzzle (Distributed coordination) • Assumption about the order in which prisoners are picked: if the prisoner waits long enough, he will get picked (fair scheduling) • Goal: Design winning strategy for prisoners so that (1) declaration is never made prematurely (2) eventually some prisoner makes declaration • For now, assume: initially switch is off Art of Multiprocessor Programming 3 Solution • At the start, prisoners choose one to be the leader, rest act as followers • Leader will be the only one to turn switch from on to off, and will count how many times he does this • Each follower will turn the switch from off to on, exactly once Art of Multiprocessor Programming 4 Each Follower’s Strategy • Local variable done, initially False • Upon entry to the room – If Done ==True do nothing – If switch is on, do nothing – If switch is off and Done==False, set Done to True and turn the switch on • Exercise: Prove that this solution is correct • Design strategy for the case when initial position of switch is not known to prisoners Art of Multiprocessor Programming 5 Leader’s Strategy • Local variable count, initially 0 • Upon entry to the room – If switch is off, do nothing – If switch is on, increment count and turn the switch off – If count == N-1 then declare that all prisoners have been to the room at least once Art of Multiprocessor Programming 6 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 Art of Multiprocessor Programming 7 Mutual Exclusion • • • • • Formal problem definitions Solutions for 2 threads Solutions for n threads Fair solutions Inherent costs Art of Multiprocessor Programming 8 Warning • You will never use these protocols • Understanding these is necessary – The same issues show up everywhere – Except hidden and more complex Art of Multiprocessor Programming 9 Formalizing the Problem • Two types of formal properties in asynchronous computation: • Safety Properties – Nothing bad happens ever – E.g. Mutual exclusion, No overtaking • Liveness Properties – Something good happens eventually – E.g. Deadlock freedom, Starvation freedom Art of Multiprocessor Programming 10 Events • An event a0 of thread A is – Instantaneous – No simultaneous events (break ties) a0 time Art of Multiprocessor Programming 11 Threads • A thread A is (formally) a sequence a0, a1, ... of events – “Trace” model – Notation: a0 a1 indicates order a0 a1 a2 … time Art of Multiprocessor Programming 12 Example Thread Events • • • • • Assign to shared variable Assign to local variable Invoke method Return from method Lots of other things … Art of Multiprocessor Programming 13 Threads are State Machines Events are transitions a3 a2 Art of Multiprocessor Programming a0 a1 14 States • Thread State – Program counter – Local variables • System state – Object fields (shared variables) – Union of thread states Art of Multiprocessor Programming 15 Concurrency • Thread A time Art of Multiprocessor Programming 16 Concurrency • Thread A time • Thread B time Art of Multiprocessor Programming 17 Interleavings • Events of two or more threads – Interleaved – Not necessarily independent (why?) time Art of Multiprocessor Programming 18 Intervals • An interval A0 =(a0,a1) is – Time between events a0 and a1 a0 A0 a1 time Art of Multiprocessor Programming 19 Intervals may Overlap b0 a0 A0 B0 b1 a1 time Art of Multiprocessor Programming 20 Intervals may be Disjoint b0 a0 A0 B0 b1 a1 time Art of Multiprocessor Programming 21 Precedence Interval A0 precedes interval B0 b0 a0 A0 B0 b1 a1 time Art of Multiprocessor Programming 22 Precedence • Notation: A0 B0 • Formally, – End event of A0 before start event of B0 – Also called “happens before” or “precedes” Art of Multiprocessor Programming 23 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! Art of Multiprocessor Programming 24 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 Art of Multiprocessor Programming 25 Total Orders (review) • Also – Irreflexive – Antisymmetric – Transitive • Except that for every distinct A, B, – Either A B or B A Art of Multiprocessor Programming 26 Repeated Events while (mumble) { a0; a1; } a0 k A0k k-th occurrence of event a0 k-th occurrence of interval A0 =(a0,a1) Art of Multiprocessor Programming 27 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 Art of Multiprocessor 28 Programming Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } Art of Multiprocessor Programming 29 Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void unlock(); } Art of Multiprocessor Programming 30 Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void unlock(); release lock } Art of Multiprocessor Programming 31 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; }} Art of Multiprocessor Programming 32 Using Locks public class Counter { private long value; private Lock lock; public long getAndIncrement() { lock.lock(); acquire try { int temp = value; value = value + 1; } finally { lock.unlock(); } return temp; }} Art of Multiprocessor Programming Lock 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 { Release lock lock.unlock(); } (no matter what) return temp; }} 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; }} Art of Multiprocessor Programming Critical section 35 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution Art of Multiprocessor Programming 36 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be thread j’s m-th critical section execution Art of Multiprocessor Programming 37 Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or Art of Multiprocessor Programming 38 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 Art of Multiprocessor Programming 39 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 Art of Multiprocessor Programming CSjm CSik 40 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 Art of Multiprocessor Programming 41 Starvation-Free • If some thread calls lock() – It will eventually return • Individual threads make progress Art of Multiprocessor Programming 42 Two-Thread vs n -Thread Solutions • Two-thread solutions first – Illustrate most basic ideas – Fits on one slide • Then n-Thread solutions Art of Multiprocessor Programming 43 Two-Thread Conventions class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; … } } Art of Multiprocessor Programming 44 Two-Thread Conventions class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; … } } Henceforth: i is current thread, j is other thread Art of Multiprocessor Programming 45 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Art of Multiprocessor Programming 46 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} Set my flag } Art of Multiprocessor Programming 47 LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} Set my flag } Wait for other flag to go false Art of Multiprocessor Programming 48 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 • Derive a contradiction Art of Multiprocessor Programming 49 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]) {} } Art of Multiprocessor Programming 50 From the Assumption • readA(flag[B]==false) writeB(flag[B]=true) • readB(flag[A]==false) writeA(flag[A]=true) Art of Multiprocessor Programming 51 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) Art of Multiprocessor Programming 52 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) Art of Multiprocessor Programming 53 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) Art of Multiprocessor Programming 54 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) Art of Multiprocessor Programming 55 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) Art of Multiprocessor Programming 56 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) Art of Multiprocessor Programming 57 Cycle! Art of Multiprocessor Programming 58 Deadlock Freedom • LockOne Fails deadlock-freedom – Concurrent execution can deadlock flag[i] = true; while (flag[j]){} flag[j] = true; while (flag[i]){} – Sequential executions OK Art of Multiprocessor Programming 59 LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} } Art of Multiprocessor Programming 60 LockTwo public class LockTwo implements Lock { private int victim; Let other public void lock() { first victim = i; while (victim == i) {}; } go public void unlock() {} } Art of Multiprocessor Programming 61 LockTwo public class LockTwo implements Lock { Wait for private int victim; public void lock() { permission victim = i; while (victim == i) {}; } public void unlock() {} } Art of Multiprocessor Programming 62 LockTwo public class Lock2 implements Lock { private int victim; public void lock() { Nothing victim = i; while (victim == i) {}; } to do public void unlock() {} } Art of Multiprocessor Programming 63 LockTwo Claims • Satisfies mutual exclusion – If thread i in CS public void LockTwo() { – Then victim == j victim = i; while (victim == i) {}; – Cannot be both 0 and 1 • Not deadlock free } – Sequential execution deadlocks – Concurrent execution does not Art of Multiprocessor Programming 64 Peterson’s Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Art of Multiprocessor Programming 65 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; } Art of Multiprocessor Programming 66 Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; Defer to other victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Art of Multiprocessor Programming 67 Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; Defer to other victim = i; while (flag[j] && victim == i) {}; } public void unlock() { Wait while other flag[i] = false; interested & I’m } the victim Art of Multiprocessor Programming 68 Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; Defer to other victim = i; while (flag[j] && victim == i) {}; } public void unlock() { Wait while other flag[i] = false; interested & I’m } No longer interested Art of Multiprocessor Programming the victim 69 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 Cannot both be true Art of Multiprocessor Programming 70 Deadlock Free public void lock() { … while (flag[j] && victim == i) {}; • 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 must not be the victim Art of Multiprocessor Programming 71 Starvation Free • Thread i blocked only if j repeatedly re-enters so that flag[j] == true victim == i • When j and 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; } Art of Multiprocessor Programming 72 The Filter Algorithm for n Threads There are n-1 “waiting rooms” called levels ncs • At each level – At least one enters level – At least one blocked if many try cs • Only one thread makes it through Art of Multiprocessor Programming 73 Filter class Filter implements Lock { int[] level; // level[i] for thread i int[] victim; // victim[L] for level L 2 public Filter(int n) { n-1 0 level = new int[n]; level 0 0 4 0 0 0 0 0 victim = new int[n]; 1 for (int i = 1; i < n; i++) { level[i] = 0; }} 2 4 … } Thread 2 at level 4 Art of Multiprocessor Programming n-1 victim 74 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; }} Art of Multiprocessor Programming 75 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 release(int i) { level[i] = 0; }} One level at a time Art of Multiprocessor Programming 76 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 release(int i) { level[i] = 0; }} Art of Multiprocessor Programming Announce intention to enter level L 77 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; }} Art of Multiprocessor Programming Give priority to anyone but me 78 Filter class Filter implements Lock { Wait as long as someone else is at int level[n]; int victim[n]; higher level, and I’m designated public void lock() { for (int L = 1; L < n; L++) { level[i] = L; victim[L] = i; same or victim while (($ k != i) level[k] >= L) && victim[L] == i); }} public void release(int i) { level[i] = 0; }} Art of Multiprocessor Programming 79 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) { Thread enters level L when level[i] = 0; the loop }} Art of Multiprocessor Programming it completes 80 Claim • Start at level L=0 • At most n-L threads enter level L • Mutual exclusion at level L=n-1 ncs L=0 L=1 L=n-2 cs L=n-1 Art of Multiprocessor Programming 81 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 cs Art of Multiprocessor Programming prove 82 Proof Structure ncs A B Assumed to enter L-1 n-L+1 = 4 Last to write victim[L] n-L+1 = 4 cs By way of contradiction all enter L Show that A must have seen B in level[L] and since victim[L] == A could not have entered Art of Multiprocessor Programming 83 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 Art of Multiprocessor Programming 84 Bounded Waiting • Want stronger fairness guarantees • Thread not “overtaken” too much • Need to adjust definitions …. Art of Multiprocessor Programming 85 Bounded Waiting • Divide lock() method into 2 parts: – Doorway interval: • Written DA • always finishes in finite steps – Waiting interval: • Written WA • may take unbounded steps Art of Multiprocessor Programming 86 First-Come First-Served • For threads A and B: – If DAk DB j • A’s k-th doorway precedes B’s j-th doorway – Then CSAk CSBj • A’s k-th critical section precedes B’s j-th critical section • B cannot overtake A Art of Multiprocessor Programming 87 Fairness Again • Filter Lock satisfies properties: – No one starves – But very weak fairness • Can be overtaken arbitrary # of times – That’s pretty lame… Art of Multiprocessor Programming 88 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 Art of Multiprocessor Programming 89 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; } } … Art of Multiprocessor Programming 90 Bakery Algorithm class Bakery implements Lock { boolean[] flag; 6 Label[] label; 2 0 n-1 public Bakery (int n) { flag = new boolean[n]; f f t f f t f f label = new Label[n]; 0 0 4 0 0 5 0 0 for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } } … CS Art of Multiprocessor Programming 91 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 92 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Doorway lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 93 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { I’m interested lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 94 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Take increasing label (read labels in some arbitrary order) lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 95 Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Someone is interested lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 96 Bakery Algorithm class Bakery implements Lock { boolean flag[n]; Someone int label[n]; is interested 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)); } With lower (label,i) in lexicographic order Art of Multiprocessor Programming 97 Bakery Algorithm class Bakery implements Lock { … public void unlock() { flag[i] = false; } } Art of Multiprocessor Programming 98 Bakery Algorithm class Bakery implements Lock { … No longer interested public void unlock() { flag[i] = false; } } labels are always increasing Art of Multiprocessor Programming 99 No Deadlock • There is always one thread with earliest label • Ties are impossible (why?) Art of Multiprocessor Programming 100 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)); } Art of Multiprocessor Programming 101 Mutual Exclusion • Suppose A and B in CS together • Suppose A has earlier label • When B entered, it must have seen 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)); } – flag[A] is false, or – label[A] > label[B] Art of Multiprocessor Programming 102 Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false Art of Multiprocessor Programming 103 Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false • LabelingB readB(flag[A]) writeA(flag[A]) LabelingA Art of Multiprocessor Programming 104 Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false • LabelingB readB(flag[A]) writeA(flag[A]) LabelingA • Which contradicts the assumption that A has an earlier label Art of Multiprocessor Programming 105 Bakery Y232K Bug class Bakery … public void flag[i] = label[i] = implements Lock { lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 106 Bakery Y232K Bug class Bakery … public void flag[i] = label[i] = Mutex breaks if label[i] overflows implements Lock { lock() { true; max(label[0], …,label[n-1])+1; while ($k flag[k] && (label[i],i) > (label[k],k)); } Art of Multiprocessor Programming 107 Does Overflow Actually Matter? • Yes – Y2K – 18 January 2038 (Unix time_t rollover) – 16-bit counters • No – 64-bit counters • Maybe – 32-bit counters Art of Multiprocessor Programming 108 Is this Optimal Solution? • The Bakery Algorithm is – Succinct, – Elegant, and – Fair. • Q: So why isn’t it practical? • A: Well, you have to read N distinct variables Art of Multiprocessor Programming 109 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 Art of Multiprocessor Programming 110 Theorem At least N MRSW (multireader/single-writer) registers are needed to solve deadlock-free mutual exclusion. N registers like Flag[]… Art of Multiprocessor Programming 111 Proving Algorithmic Impossibility •To show no algorithm exists: • assume by way of contradiction C write one does, • show a bad execution that CS violates properties: • in our case assume an alg for deadlock free mutual exclusion using < N registers Art of Multiprocessor Programming 112 Proof: Need N-MRSW Registers Each thread must write to some register A CS B C write write CS CS …can’t tell whether A is in critical section Art of Multiprocessor Programming 113 Upper Bound • Bakery algorithm – Uses 2N MRSW registers • So the bound is (pretty) tight • But what if we use MRMW registers? – Like victim[] ? Art of Multiprocessor Programming 114 Bad News Theorem At least N MRMW multireader/multi-writer registers are needed to solve deadlock-free mutual exclusion. (So multiple writers don’t help) Art of Multiprocessor Programming 115 Theorem (For 2Threads) 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 Art of Multiprocessor Programming 116 Two Thread Execution A B R Write(R) CS CS • Threads run, reading and writing R • Deadlock free so at least one gets in Art of Multiprocessor Programming 117 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 Art of Multiprocessor Programming 118 Proof: Assume Cover of 1 A B Write(R) CS A runs, possibly writes to the register, enters CS Art of Multiprocessor Programming 119 Proof: Assume Cover of 1 A B Write(R) CS CS Art of Multiprocessor Programming B Runs, first obliterating any trace of A, then also enters the critical section 120 Theorem Deadlock-free mutual exclusion for 3 threads requires at least 3 multireader multi-writer registers Art of Multiprocessor Programming 121 Proof: Assume Cover of 2 A B C Write(RB) Write(RC) Only 2 registers Art of Multiprocessor Programming 122 Run A Solo A B C Write(RB) Write(RC) Writes to one or both CS registers, enters CS Art of Multiprocessor Programming 123 Obliterate Traces of A A CS B C Write(RB) Write(RC) Other threads obliterate evidence that A entered CS Art of Multiprocessor Programming 124 Mutual Exclusion Fails A CS B C Write(RB) Write(RC) CS CS looks empty, so another thread gets in Art of Multiprocessor Programming 125 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 Art of Multiprocessor Programming 126 Covering State for Two A B Write(RA) Write(RB) • If we run B through CS 3 times, B must return twice to cover some register, say RB Art of Multiprocessor Programming 127 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? Art of Multiprocessor Programming 128 Covering State for Two A B Write(RA) Write(RB) • NO! A could have written to RB • So CS no longer looks empty Art of Multiprocessor Programming 129 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 Art of Multiprocessor Programming 130 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 Art of Multiprocessor Programming 131 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 Art of Multiprocessor Programming 132 Summary of Lecture • N RW-Registers inefficient – Because writes “cover” older writes • Need stronger hardware operations – that do not have the “covering problem” Art of Multiprocessor Programming 133 Muddy children’s puzzle (Common Knowledge) • A group of kids are playing. A stranger walks by and announces “Some of you have mud on your forehead • Each kid can see everyone else’s forehead, but not his/her own (and they don’t talk to one another) • Stranger says “Raise your hand if you conclude that you have mud on your forehead”. Nobody does. • Stranger keeps on repeating the statement. • If k kids have muddy foreheads, then exactly these k kids raise their hands after the stranger repeats the statement exactly k times Art of Multiprocessor Programming 134