Mutual Exclusion

128
Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Pavol Černý, Programming Paradigms for Concurrency, Fall 2010, IST Austria

description

Mutual Exclusion. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Pavol Černý , Programming Paradigms for Concurrency , Fall 2010, IST Austria. Review: Peterson’s Algorithm. Bob. flag[0] ←0. flag[1] ←0. Alice. no access. - PowerPoint PPT Presentation

Transcript of Mutual Exclusion

Page 1: Mutual Exclusion

Mutual Exclusion

Companion slides forThe Art of Multiprocessor Programming

by Maurice Herlihy & Nir Shavit

Modified by Pavol Černý, Programming Paradigms for

Concurrency, Fall 2010, IST Austria

Page 2: Mutual Exclusion

Review: Peterson’s Algorithm

flag[0]

← 0

no access

flag[0] ←0

flag[1] = 0 or

turn = 0

access

request

flag[0] ← 1

turn ← 1 flag[0]

← 0

no access

flag[1] ←0

access

request

flag[1] ← 1

turn ← 0

Alice Bob

flag[0] = 0 or

turn = 1

Page 3: Mutual Exclusion

Art of Multiprocessor Programming

3

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

Use Peterson’s

Page 4: Mutual Exclusion

Art of Multiprocessor Programming

4

Locks (Mutual Exclusion)

public interface Lock {

public void lock();

public void unlock();}

Page 5: Mutual Exclusion

Art of Multiprocessor Programming

5

Locks (Mutual Exclusion)

public interface Lock {

public void lock();

public void unlock();}

acquire lock

Page 6: Mutual Exclusion

Art of Multiprocessor Programming

6

Locks (Mutual Exclusion)

public interface Lock {

public void lock();

public void unlock();}

release lock

acquire lock

Page 7: Mutual Exclusion

Art of Multiprocessor Programming

7

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; }}

Page 8: Mutual Exclusion

Art of Multiprocessor Programming

8

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

Page 9: Mutual Exclusion

Art of Multiprocessor Programming

9

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)

Page 10: Mutual Exclusion

Art of Multiprocessor Programming

10

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

Page 11: Mutual Exclusion

Peterson’s in Javapublic void lock() { flag[i] = 1; turn = 1-i; while (!((flag[1-i] == 0) || (turn == i))) { }}

public void unlock() { flag[i] = 0;}

flag[0]

← 0

no access

flag[0] ←0

flag[1] = 0 or

turn = 0

access

request

flag[0] ← 1

turn ← 1

Page 12: Mutual Exclusion

Questions from last lecture:

1.Can we make do with two shared bits (instead of three)?2.How can one extend this idea to n processes?3.Does the algorithm work in Java?

Run it and see. What is the problem?

Where is the fault in our proof?

Review: Peterson’s Algorithm

Page 13: Mutual Exclusion

Question 1: Modify Peterson’s to use two bits

public void lock() { if (i==0) { flag[0] = 1;

while (!(flag[1] == 0)) { } } else {

while (!( flag[1] == 1)) {; flag[1] = 1;

while (!(flag[0] == 0)) { flag[1] = 0; }}

}}

public void unlock() { flag[i] = 0;}

Page 14: Mutual Exclusion

Question 2: Modify Peterson’s for n processes

Today’s class

Page 15: Mutual Exclusion

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;}

Page 16: Mutual Exclusion

Art of Multiprocessor Programming

16

Fact

• Most hardware architectures don’t support sequential consistency

• Because they think it’s too strong

Page 17: Mutual Exclusion

Art of Multiprocessor Programming

17

The Flag Example

time

x.write(1) y.read(0)

y.write(1) x.read(0)

time

Page 18: Mutual Exclusion

Art of Multiprocessor Programming

18

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

Page 19: Mutual Exclusion

Art of Multiprocessor Programming

19

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

Page 20: Mutual Exclusion

Art of Multiprocessor Programming

20

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 …

Page 21: Mutual Exclusion

Art of Multiprocessor Programming

21

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!

Page 22: Mutual Exclusion

Art of Multiprocessor Programming

22

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

Page 23: Mutual Exclusion

Art of Multiprocessor Programming

23

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

Page 24: Mutual Exclusion

Art of Multiprocessor Programming

24

Explicit Synchronization

• Memory barrier instruction– Flush unwritten caches– Bring caches up to date

• Expensive

Page 25: Mutual Exclusion

Art of Multiprocessor Programming

25

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;

Page 26: Mutual Exclusion

Art of Multiprocessor Programming

26

Mutual Exclusion

• Problem definitions• Solutions for 2 threads• Solutions for n threads• Fair solutions• Inherent costs

Page 27: Mutual Exclusion

Art of Multiprocessor Programming

27

Warning

• You will never use these protocols• Understanding these is necessary

– The same issues show up everywhere– Except hidden and more complex

Page 28: Mutual Exclusion

Art of Multiprocessor Programming 28

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

Page 29: Mutual Exclusion

Art of Multiprocessor Programming

29

time

• An event a0 of thread A is– Instantaneous– No simultaneous events (break ties)

a0

Events

Page 30: Mutual Exclusion

Art of Multiprocessor Programming

30

time

• A thread A is (formally) a sequence a0, a1, ... of events – “Trace” model

– Notation: a0 a1 indicates order

a0

Threads

a1 a2 …

Page 31: Mutual Exclusion

Art of Multiprocessor Programming

31

• Assign to shared variable• Assign to local variable• Invoke method• Return from method• Lots of other things …

Example Thread Events

Page 32: Mutual Exclusion

Art of Multiprocessor Programming

32

Threads are State Machines

Events are transitions

a0

a1a2

a3

Page 33: Mutual Exclusion

Art of Multiprocessor Programming

33

States

• Thread State– Program counter– Local variables

• System state– Object fields (shared variables)– Union of thread states

Page 34: Mutual Exclusion

Art of Multiprocessor Programming

34

time

• Thread A

Concurrency

Page 35: Mutual Exclusion

Art of Multiprocessor Programming

35

time

time

• Thread A

• Thread B

Concurrency

Page 36: Mutual Exclusion

Art of Multiprocessor Programming

36

time

Interleavings

• Events of two or more threads– Interleaved– Not necessarily independent (why?)

Page 37: Mutual Exclusion

Art of Multiprocessor Programming

37

time

• An interval A0 =(a0,a1) is

– Time between events a0 and a1

a0 a1

Intervals

A0

Page 38: Mutual Exclusion

Art of Multiprocessor Programming

38

time

Intervals may Overlap

a0 a1A0

b0 b1B0

Page 39: Mutual Exclusion

Art of Multiprocessor Programming

39

time

Intervals may be Disjoint

a0 a1A0

b0 b1B0

Page 40: Mutual Exclusion

Art of Multiprocessor Programming

40

time

Precedence

a0 a1A0

b0 b1B0

Interval A0 precedes interval B0

Page 41: Mutual Exclusion

Art of Multiprocessor Programming

41

Precedence

• Notation: A0 B0

• Formally,– End event of A0 before start event of B0

– Also called “happens before” or “precedes”

Page 42: Mutual Exclusion

Art of Multiprocessor Programming

42

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!

Page 43: Mutual Exclusion

Art of Multiprocessor Programming

43

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

Page 44: Mutual Exclusion

Art of Multiprocessor Programming

44

Total Orders(review)

• Also– Irreflexive– Antisymmetric– Transitive

• Except that for every distinct A, B,– Either A B or B A

Page 45: Mutual Exclusion

Art of Multiprocessor Programming

45

Repeated Events

while (mumble) { a0; a1;}

a0k

k-th occurrence of event a0

A0k

k-th occurrence of interval A0 =(a0,a1)

Page 46: Mutual Exclusion

Art of Multiprocessor Programming

46

Mutual Exclusion

• Let CSik be thread i’s k-th critical

section execution

Page 47: Mutual Exclusion

Art of Multiprocessor Programming

47

Mutual Exclusion

• Let CSik be thread i’s k-th critical

section execution

• And CSjm be thread j’s m-th critical

section execution

Page 48: Mutual Exclusion

Art of Multiprocessor Programming

48

Mutual Exclusion

• Let CSik be thread i’s k-th critical

section execution

• And CSjm be j’s m-th execution

• Then either– or

Page 49: Mutual Exclusion

Art of Multiprocessor Programming

49

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 CSj

m

Page 50: Mutual Exclusion

Art of Multiprocessor Programming

50

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 CSj

m

CSjm CSi

k

Page 51: Mutual Exclusion

Art of Multiprocessor Programming

51

Deadlock-Free• If some thread calls lock()

– And never returns– Then other threads must complete

lock() and unlock() calls infinitely often

– This is true for all fair schedules– Schedule is fair if all threads in CS or

concurrency parts proceed

• System as a whole makes progress– Even if individuals starve

Page 52: Mutual Exclusion

Art of Multiprocessor Programming

52

Starvation-Free

• If some thread calls lock()– It will eventually return

• Individual threads make progress

Page 53: Mutual Exclusion

Art of Multiprocessor Programming

53

Example – proving mutual exclusion

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

Page 54: Mutual Exclusion

Art of Multiprocessor Programming

54

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

Set my flag

Page 55: Mutual Exclusion

Art of Multiprocessor Programming

55

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

LockOne

Wait for other flag to go false

Set my flag

Page 56: Mutual Exclusion

Art of Multiprocessor Programming

56

• Assume CSAj overlaps CSB

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

Page 57: Mutual Exclusion

Art of Multiprocessor Programming

57

• writeA(flag[A]=true) readA(flag[B]==false) CSA

• writeB(flag[B]=true) readB(flag[A]==false) CSB

From the Code

class LockOne implements Lock {… public void lock() { flag[i] = true; while (flag[j]) {} }

Page 58: Mutual Exclusion

Art of Multiprocessor Programming

58

• readA(flag[B]==false) writeB(flag[B]=true)

• readB(flag[A]==false) writeA(flag[A]=true)

From the Assumption

Page 59: Mutual Exclusion

Art of Multiprocessor Programming

59

• 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)

Combining

Page 60: Mutual Exclusion

Art of Multiprocessor Programming

60

• 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)

Combining

Page 61: Mutual Exclusion

Art of Multiprocessor Programming

61

• 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)

Combining

Page 62: Mutual Exclusion

Art of Multiprocessor Programming

62

• 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)

Combining

Page 63: Mutual Exclusion

Art of Multiprocessor Programming

63

• 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)

Combining

Page 64: Mutual Exclusion

Art of Multiprocessor Programming

64

• 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)

Combining

Page 65: Mutual Exclusion

Art of Multiprocessor Programming

65

Cycle!

Imposs

ible

in p

artial a

order

Page 66: Mutual Exclusion

Art of Multiprocessor Programming

66

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]){}

Page 67: Mutual Exclusion

Art of Multiprocessor Programming

67

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

Page 68: Mutual Exclusion

Art of Multiprocessor Programming

68

Filterclass 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

n-1

0

1

0 0 0 0 0 04

2

2

Thread 2 at level 4

0

4

Page 69: Mutual Exclusion

Art of Multiprocessor Programming

69

Filterclass 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; }}

Page 70: Mutual Exclusion

Art of Multiprocessor Programming

70

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

Page 71: Mutual Exclusion

Art of Multiprocessor Programming

71

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

Page 72: Mutual Exclusion

Art of Multiprocessor Programming

72

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

Page 73: Mutual Exclusion

Art of Multiprocessor Programming

73

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; }}

FilterWait as long as someone else is at

same or higher level, and I’m designated victim

Page 74: Mutual Exclusion

Art of Multiprocessor Programming

74

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

Page 75: Mutual Exclusion

Art of Multiprocessor Programming

75

Claim• Start at level L=0• At most n-L threads enter level L• Mutual exclusion at level L=n-1

ncs

cs L=n-1

L=1

L=n-2

L=0

Page 76: Mutual Exclusion

Art of Multiprocessor Programming

76

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 or above • Induction step: by contradiction

ncs

cs

L-1 has n-L+1L has n-L

assume

prove

Page 77: Mutual Exclusion

Art of Multiprocessor Programming

77

Proof Structurencs

cs

Assumed to enter L-1

By way of contradictionall enter L

n-L+1 = 4

n-L+1 = 4

A B

Last to writevictim[L]

A must have seen B in level[L] and since victim[L] == Acould not have entered

Page 78: Mutual Exclusion

Art of Multiprocessor Programming

78

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

Page 79: Mutual Exclusion

Art of Multiprocessor Programming

79

Bounded Waiting

• Want stronger fairness guarantees• Thread not “overtaken” too much• Need to adjust definitions ….

Page 80: Mutual Exclusion

Art of Multiprocessor Programming

80

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

Page 81: Mutual Exclusion

Art of Multiprocessor Programming

81

• For threads A and B:– If DA

k DB j

• A’s k-th doorway precedes B’s j-th doorway

– Then CSAk CSB

j

• A’s k-th critical section precedes B’s j-th critical section

• B cannot overtake A

First-Come First-Served

Page 82: Mutual Exclusion

Break!

Art of Multiprocessor Programming

82

Page 83: Mutual Exclusion

Art of Multiprocessor Programming

83

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

Page 84: Mutual Exclusion

Art of Multiprocessor Programming

84

Bakery Algorithmclass 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; } } …

Page 85: Mutual Exclusion

Art of Multiprocessor Programming

85

Bakery Algorithmclass 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-10

f f f f t ft

2

f

0 0 0 0 5 04 0

6

CS

Page 86: Mutual Exclusion

Art of Multiprocessor Programming

86

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)); }

Page 87: Mutual Exclusion

Art of Multiprocessor Programming

87

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

Page 88: Mutual Exclusion

Art of Multiprocessor Programming

88

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

Page 89: Mutual Exclusion

Art of Multiprocessor Programming

89

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)

Page 90: Mutual Exclusion

Art of Multiprocessor Programming

90

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

Page 91: Mutual Exclusion

Art of Multiprocessor Programming

91

Bakery Algorithmclass Bakery implements Lock { boolean flag[n]; int label[n];

public void lock() { flag[i] = true; label[i] = max(label[0], …,label[n-1])+1;

while (k flag[k] && (label[i],i) > (label[k],k));

}

Someone is interested

With lower (label,i) in

lexicographic order

Page 92: Mutual Exclusion

Art of Multiprocessor Programming

92

Bakery Algorithm

class Bakery implements Lock { …

public void unlock() { flag[i] = false; }}

Page 93: Mutual Exclusion

Art of Multiprocessor Programming

93

Bakery Algorithm

class Bakery implements Lock { …

public void unlock() { flag[i] = false; }}

No longer interested

labels are always increasing

Page 94: Mutual Exclusion

Art of Multiprocessor Programming

94

No Deadlock

• There is always one thread with earliest label

• Ties are impossible (why?)

Page 95: Mutual Exclusion

Art of Multiprocessor Programming

95

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));

}

Page 96: Mutual Exclusion

Art of Multiprocessor Programming

96

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));

}

Page 97: Mutual Exclusion

Art of Multiprocessor Programming

97

Mutual Exclusion

• Labels are strictly increasing so

• B must have seen flag[A] == false

Page 98: Mutual Exclusion

Art of Multiprocessor Programming

98

Mutual Exclusion

• Labels are strictly increasing so

• B must have seen flag[A] == false

• LabelingB readB(flag[A]) writeA(flag[A]) LabelingA

Page 99: Mutual Exclusion

Art of Multiprocessor Programming

99

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

Page 100: Mutual Exclusion

Art of Multiprocessor Programming

100

Bakery Y232K Bugclass 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)); }

Page 101: Mutual Exclusion

Art of Multiprocessor Programming

101

Bakery Y232K Bugclass 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

Page 102: Mutual Exclusion

Art of Multiprocessor Programming

102

Does Overflow Actually Matter?

• Yes– Y2K– 18 January 2038 (Unix time_t rollover)– 16-bit counters

• No– 64-bit counters

• Maybe– 32-bit counters

Page 103: Mutual Exclusion

Art of Multiprocessor Programming

103

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

Page 104: Mutual Exclusion

Art of Multiprocessor Programming

104

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

Page 105: Mutual Exclusion

Art of Multiprocessor Programming

105

Theorem

At least N MRSW (multi-reader/single-writer) registers are needed to solve deadlock-free mutual exclusion.

N registers like Flag[]…

Page 106: Mutual Exclusion

Art of Multiprocessor Programming

106

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

Page 107: Mutual Exclusion

Art of Multiprocessor Programming

107

Proof: Need N-MRSW RegistersEach thread must write to some register

…can’t tell whether A is in critical section

write

CS CS CS

write

A B C

Page 108: Mutual Exclusion

Art of Multiprocessor Programming

108

Upper Bound

• Bakery algorithm– Uses 2N MRSW registers

• So the bound is (pretty) tight• But what if we use MRMW

registers?– Like victim[] ?

Page 109: Mutual Exclusion

Art of Multiprocessor Programming

109

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)

Page 110: Mutual Exclusion

Art of Multiprocessor Programming

110

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

Page 111: Mutual Exclusion

Art of Multiprocessor Programming

111

Two Thread Execution

• Threads run, reading and writing R• Deadlock free so at least one gets in

BA

CS

Write(R)

CS

R

Page 112: Mutual Exclusion

Art of Multiprocessor Programming

112

Covering State

Write(R)

B

A covering state for a Lock object is one in which there is at least one thread about to write to each shared location, but the object’s locations appear as if no thread is in the critical section or trying to enter the critical section.

Page 113: Mutual Exclusion

Art of Multiprocessor Programming

113

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

Page 114: Mutual Exclusion

Art of Multiprocessor Programming

114

Proof: Assume Cover of 1

A B

Write(R)

CS

A runs, possibly writes to the register, enters CS

Page 115: Mutual Exclusion

Art of Multiprocessor Programming

115

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

Page 116: Mutual Exclusion

Art of Multiprocessor Programming

116

Theorem

Deadlock-free mutual exclusion for 3 threads requires at least 3 multi-reader multi-writer registers

Page 117: Mutual Exclusion

Art of Multiprocessor Programming

117

Proof: Assume Cover of 2

Write(RB)

B

Write(RC)

CA

Only 2 registers

Page 118: Mutual Exclusion

Art of Multiprocessor Programming

118

Run A Solo

Write(RB)

B

Write(RC)

CA

Writes to one or both registers, enters CS CS

Page 119: Mutual Exclusion

Art of Multiprocessor Programming

119

Obliterate Traces of A

Write(RB)

B

Write(RC)

CA

Other threads obliterate evidence that A entered CS CS

Page 120: Mutual Exclusion

Art of Multiprocessor Programming

120

Mutual Exclusion Fails

Write(RB)

B

Write(RC)

CA

CS CS

CS looks empty, so another thread

gets in

Page 121: Mutual Exclusion

Art of Multiprocessor Programming

121

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

Page 122: Mutual Exclusion

Art of Multiprocessor Programming

122

• If we run B through CS 3 times, B must return twice to cover some register, say RB

Covering State for Two

Write(RB)

B

Write(RA)

A

Page 123: Mutual Exclusion

Art of Multiprocessor Programming

123

Covering State for Two

• Start with B covering register RB for the 1st time • Run A until it is about to write to uncovered RA

• Are we done?

Write(RB)

B

Write(RA)

A

Page 124: Mutual Exclusion

Art of Multiprocessor Programming

124

Covering State for Two

• NO! A could have written to RB

• So CS no longer looks empty

Write(RB)

B

Write(RA)

A

Page 125: Mutual Exclusion

Art of Multiprocessor Programming

125

Covering State for Two

• Run B obliterating traces of A in RB

• Run B again until it is about to write to RB

• Now we are done

Write(RB)

B

Write(RA)

A

Page 126: Mutual Exclusion

Art of Multiprocessor Programming

126

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

• Reference:J. Burns, N. Lynch : Bounds on shared memory for mutual exclusion. Inf. And Comp. 1993

Page 127: Mutual Exclusion

Art of Multiprocessor Programming

127

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

Page 128: Mutual Exclusion

Art of Multiprocessor Programming

128

Summary of Lecture

• N RW-Registers inefficient– Because writes “cover” older writes

• Need stronger hardware operations – that do not have the “covering

problem”