Download presentation
Presentation is loading. Please wait.
Published byMerry Ward Modified over 8 years ago
1
Mutual Exclusion
2
Art of Multiprocessor Programming 2 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
3
Art of Multiprocessor Programming 3 Mutual Exclusion Formal problem definitions Solutions for 2 threads Solutions for n threads Fair solutions Inherent costs
4
Art of Multiprocessor Programming 4 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
5
Art of Multiprocessor Programming 5 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
6
Art of Multiprocessor Programming 6 “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) Time time
7
Art of Multiprocessor Programming 7 time An event a 0 of thread A is –Instantaneous –No simultaneous events (break ties) a0a0 Events
8
Art of Multiprocessor Programming 8 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 …
9
Art of Multiprocessor Programming 9 Assign to shared variable Assign to local variable Invoke method Return from method Lots of other things … Example Thread Events
10
Art of Multiprocessor Programming 10 Threads are State Machines Events are transitions a0a0 a1a1 a2a2 a3a3
11
Art of Multiprocessor Programming 11 States Thread State –Program counter –Local variables System state –Object fields (shared variables) –Union of thread states
12
Art of Multiprocessor Programming 12 time Thread A Concurrency
13
Art of Multiprocessor Programming 13 time Thread A Thread B Concurrency
14
Art of Multiprocessor Programming 14 time Interleavings Events of two or more threads –Interleaved –Not necessarily independent (why?)
15
Art of Multiprocessor Programming 15 time An interval A 0 =(a 0,a 1 ) is –Time between events a 0 and a 1 a0a0 a1a1 Intervals A0A0
16
Art of Multiprocessor Programming 16 time Intervals may Overlap a0a0 a1a1 A0A0 b0b0 b1b1 B0B0
17
Art of Multiprocessor Programming 17 time Intervals may be Disjoint a0a0 a1a1 A0A0 b0b0 b1b1 B0B0
18
Art of Multiprocessor Programming 18 time Precedence a0a0 a1a1 A0A0 b0b0 b1b1 B0B0 Interval A 0 precedes interval B 0
19
Art of Multiprocessor Programming 19 Precedence Notation: A 0 B 0 Formally, –End event of A 0 before start event of B 0 –Also called “happens before” or “precedes”
20
Art of Multiprocessor Programming 20 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?
21
Art of Multiprocessor Programming 21 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!
22
Art of Multiprocessor Programming 22 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
23
Art of Multiprocessor Programming 23 Total Orders (review) Also –Irreflexive –Antisymmetric –Transitive Except that for every distinct A, B, –Either A B or B A
24
Art of Multiprocessor Programming 24 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 )
25
Art of Multiprocessor Programming 25 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
26
Art of Multiprocessor Programming 26 Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); }
27
Art of Multiprocessor Programming 27 Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } acquire lock
28
Art of Multiprocessor Programming 28 Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } release lock acquire lock
29
Art of Multiprocessor Programming 29 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; }}
30
Art of Multiprocessor Programming 30 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
31
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; }} Release lock (no matter what)
32
Art of Multiprocessor Programming 32 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
33
Art of Multiprocessor Programming 33 Mutual Exclusion Let CS i k be thread i’s k-th critical section execution
34
Art of Multiprocessor Programming 34 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
35
Art of Multiprocessor Programming 35 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
36
Art of Multiprocessor Programming 36 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
37
Art of Multiprocessor Programming 37 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
38
Art of Multiprocessor Programming 38 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
39
Art of Multiprocessor Programming 39 Starvation-Free If some thread calls lock() –It will eventually return Individual threads make progress
40
Art of Multiprocessor Programming 40 Two-Thread vs n -Thread Solutions 2-thread solutions first –Illustrate most basic ideas –Fits on one slide Then n-thread solutions
41
Art of Multiprocessor Programming 41 class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = ThreadID.get(); int j = 1 - i; … } Two-Thread Conventions
42
Art of Multiprocessor Programming 42 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
43
LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} }
44
LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Each thread has flag
45
LockOne class LockOne implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Set my flag
46
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
47
Art of Multiprocessor Programming 47 Assume CS A j overlaps CS B k Consider each thread's last (j-th and k-th) read and write in the lock() method before entering Derive a contradiction LockOne Satisfies Mutual Exclusion
48
Art of Multiprocessor Programming 48 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]) {} }
49
Art of Multiprocessor Programming 49 read A (flag[B]==false) write B (flag[B]=true) read B (flag[A]==false) write A (flag[A]=true) From the Assumption
50
Art of Multiprocessor Programming 50 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
51
Art of Multiprocessor Programming 51 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
52
Art of Multiprocessor Programming 52 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
53
Art of Multiprocessor Programming 53 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
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 Cycle! Impossible in a partial order
57
Art of Multiprocessor Programming 57 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]){}
58
Art of Multiprocessor Programming 58 LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} }
59
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() {} } Let other go first
60
Art of Multiprocessor Programming 60 LockTwo public class LockTwo implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} } Wait for permission
61
Art of Multiprocessor Programming 61 LockTwo public class Lock2 implements Lock { private int victim; public void lock() { victim = i; while (victim == i) {}; } public void unlock() {} } Nothing to do
62
Art of Multiprocessor Programming 62 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
63
Art of Multiprocessor Programming 63 Peterson’s Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; }
64
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; } Announce I’m interested
65
Art of Multiprocessor Programming 65 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
66
Art of Multiprocessor Programming 66 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
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; } No longer interested Announce I’m interested Defer to other Wait while other interested & I’m the victim
68
Art of Multiprocessor Programming 68 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
69
Art of Multiprocessor Programming 69 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) {}; }
70
Art of Multiprocessor Programming 70 Assumption W.L.O.G. assume A is the last thread to write victim (3) write B (victim=B) write A (victim=A)
71
Art of Multiprocessor Programming 71 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) Thus, A read flag[B] == true and victim == A, so it could not have entered the CS QED
72
Art of Multiprocessor Programming 72 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) {};
73
Art of Multiprocessor Programming 73 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; }
74
Question 3: But does it work in Java? java Peterson … (results in deadlock) java Peterson... (mutual exclusion fails (if a counter is protected with these locks, we observe a problem after enough iterations) ) public void lock() { flag[i] = 1; turn = 1-i; while (!((flag[1-i] == 0) || (turn == i))) { } } public void unlock() { flag[i]=0; }
75
Art of Multiprocessor Programming 75 Fact Most hardware architectures don ’ t support sequential consistency Because they think it ’ s too strong
76
Art of Multiprocessor Programming 76 The Flag Example time x.write(1) y.read(0) y.write(1) x.read(0) Each thread ’ s view is sequentially consistent –It went first
77
Art of Multiprocessor Programming 77 The Flag Example time x.write(1) y.read(0) y.write(1) x.read(0) Entire history isn ’ t sequentially consistent –Can ’ t both go first
78
Art of Multiprocessor Programming 78 The Flag Example time x.write(1) y.read(0) y.write(1) x.read(0) Is this behavior really so wrong? –We can argue either way …
79
Art of Multiprocessor Programming 79 Opinion1: It ’ s Wrong This pattern –Write mine, read yours Is exactly the flag principle –Beloved of Alice and Bob –Heart of mutual exclusion Peterson Bakery, etc. It ’ s non-negotiable!
80
Art of Multiprocessor Programming 80 Opinion2: But It Feels So Right … Many hardware architects think that sequential consistency is too strong Too expensive to implement in modern hardware OK if flag principle –violated by default –Honored by explicit request
81
Art of Multiprocessor Programming 81 Who knew you wanted to synchronize? Writing to memory = mailing a letter Vast majority of reads & writes –Not for synchronization –No need to idle waiting for post office If you want to synchronize –Announce it explicitly –Pay for it only when you need it
82
Art of Multiprocessor Programming 82 Explicit Synchronization Memory barrier instruction –Flush unwritten caches –Bring caches up to date Expensive
83
Art of Multiprocessor Programming 83 Volatile In Java, can ask compiler to keep a variable up-to-date with volatile keyword Also inhibits reordering & other “ optimizations ” Example: public static volatile int[] flag; public static volatile int z = 0;
84
Question Can this result in i=0 and j=0?
85
Answer: Yes! How can i=0 and j=0?
86
Working Memory v.s. Main Memory Every thread has a working memory in which it keeps its own working copy of variables that it must use or assign. As the thread executes a program, it operates on these working copies. The main memory contains the master copy of every variable.
87
Low level actions
88
How can this happen? Compiler can reorder statement or keep values in registers Processor can reorder them On multiprocessor, values not synchronized in global memory Must use synchronization to enforce visibility and ordering as well as mutual exclusion
89
Synchronization Action //block until obtain lock synchronized (anObject) { //get main memory value of field1 and field2 int x = anObject.field1; int y = anObject.field2; anObject.field3 = x + y; //commit value of field3 to main memory } // release lock moreCode();
90
When are actions visible to other thread?
91
What does volatile mean? C/C++ spec --There is no implementation independent meaning of volatile Situation a little better with Java Technology --volatile reads/writes guaranteed to go directly to main memory e.g. can’t be cached in registers or local memory
92
Using volatile Volatile used to guarantee visibility of writes --stop() must be declared volatile --Otherwise, compiler could keep in register class Animator implements Runnable { private volatile boolean stop = false; public void stop() { stop = true;} public void run() { while (!stop) oneStep(); } private void oneStep() {/*……*/} }
93
Art of Multiprocessor Programming 93 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
94
Art of Multiprocessor Programming 94 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
95
Art of Multiprocessor Programming 95 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; }}
96
Art of Multiprocessor Programming 96 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
97
Art of Multiprocessor Programming 97 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
98
Art of Multiprocessor Programming 98 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
99
Art of Multiprocessor Programming 99 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
100
Art of Multiprocessor Programming 100 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
101
Art of Multiprocessor Programming 101 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
102
Art of Multiprocessor Programming 102 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
103
Art of Multiprocessor Programming 103 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
104
Art of Multiprocessor Programming 104 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
105
Art of Multiprocessor Programming 105 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) {}; }}
106
Art of Multiprocessor Programming 106 By Assumption By assumption, A is the last thread to write victim[L] (3) write B (victim[L]=B) write A (victim[L]=A)
107
Art of Multiprocessor Programming 107 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])
108
Art of Multiprocessor Programming 108 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])
109
Art of Multiprocessor Programming 109 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]) readA(victim[L]) Thus, A read level[B] ≥ L, and victim[L] = A, so it could not have entered level L!
110
Art of Multiprocessor Programming 110 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
111
Art of Multiprocessor Programming 111 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
112
Art of Multiprocessor Programming 112 Theorem At least N MRSW (multi- reader/single-writer) registers are needed to solve deadlock-free mutual exclusion. N registers like Flag[]…
113
Art of Multiprocessor Programming 113 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
114
Art of Multiprocessor Programming 114 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…
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.