Presentation is loading. Please wait.

Presentation is loading. Please wait.

Mutual Exclusion. Art of Multiprocessor Programming 2 Mutual Exclusion We will clarify our understanding of mutual exclusion We will also show you how.

Similar presentations


Presentation on theme: "Mutual Exclusion. Art of Multiprocessor Programming 2 Mutual Exclusion We will clarify our understanding of mutual exclusion We will also show you how."— Presentation transcript:

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…


Download ppt "Mutual Exclusion. Art of Multiprocessor Programming 2 Mutual Exclusion We will clarify our understanding of mutual exclusion We will also show you how."

Similar presentations


Ads by Google