Art of Multiprocessor Programming

advertisement
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
Download