ch02herlihy

advertisement
Mutual Exclusion
Companion slides for
The Art of Multiprocessor
Programming
by Maurice Herlihy & Nir Shavit
Mutual Exclusion
In his 1965 paper E. W. Dijkstra wrote:
"Given in this paper is a solution to a problem which,
to the knowledge of the author, has been an open
question since at least 1962, irrespective of the
solvability. [...] Although the setting of the
problem might seem somewhat academic at first,
the author trusts that anyone familiar with the
logical problems that arise in computer coupling
will appreciate the significance of the fact that
this problem indeed can be solved."
Art of Multiprocessor
Programming
2
Time
• “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
Art of Multiprocessor
Programming
3
Events
• An event a0 of thread A is
– Instantaneous
– No simultaneous events (break ties)
a0
time
Art of Multiprocessor
Programming
4
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
5
Example Thread Events
•
•
•
•
•
Assign to shared variable
Assign to local variable
Invoke method
Return from method
Lots of other things …
Art of Multiprocessor
Programming
6
Threads are State Machines
Events are
transitions
a3
a2
Art of Multiprocessor
Programming
a0
a1
7
States
• Thread State
– Program counter
– Local variables
• System state
– Object fields (shared variables)
– Union of thread states
Art of Multiprocessor
Programming
8
Concurrency
• Thread A
time
Art of Multiprocessor
Programming
9
Concurrency
• Thread A
time
• Thread B
time
Art of Multiprocessor
Programming
10
Interleavings
• Events of two or more threads
– Interleaved
– Not necessarily independent (why?)
time
Art of Multiprocessor
Programming
11
Intervals
• An interval A0 =(a0,a1) is
– Time between events a0 and a1
a0
A0
a1
time
Art of Multiprocessor
Programming
12
Intervals may Overlap
b0
a0
A0
B0
b1
a1
time
Art of Multiprocessor
Programming
13
Intervals may be Disjoint
b0
a0
A0
B0
b1
a1
time
Art of Multiprocessor
Programming
14
Precedence
Interval A0 precedes interval B0
b0
a0
A0
B0
b1
a1
time
Art of Multiprocessor
Programming
15
Precedence
• Notation: A0  B0
• Formally,
– End event of A0 before start event of B0
– Also called “happens before” or
“precedes”
Art of Multiprocessor
Programming
16
Precedence Ordering
• Remark: A0  B0 is just like saying
– 1066 AD  1492 AD,
– Middle Ages  Renaissance,
• Oh wait,
– what about this week vs this month?
Art of Multiprocessor
Programming
17
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
18
Partial Orders
(you may know this already)
• 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
19
Total Orders
(you may know this already)
• Also
– Irreflexive
– Antisymmetric
– Transitive
• Except that for every distinct A, B,
– Either A  B or B  A
Art of Multiprocessor
Programming
20
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
21
Locks (Mutual Exclusion)
public interface Lock {
public void lock();
public void unlock();
}
Art of Multiprocessor
Programming
22
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
23
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
24
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
25
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
26
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
27
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
28
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
29
LockOne
class LockOne implements Lock {
private boolean[] flag =
new boolean[2];
public void lock() {
flag[i] = true;
while (flag[j]) {}
}
Art of Multiprocessor
Programming
30
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
31
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
32
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
33
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
34
From the Assumption
• readA(flag[B]==false) 
writeB(flag[B]=true)
• readB(flag[A]==false) 
writeA(flag[B]=true)
Art of Multiprocessor
Programming
35
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
36
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
37
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
38
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
39
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
40
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
41
Cycle!
Art of Multiprocessor
Programming
42
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
43
LockTwo
public class LockTwo implements Lock {
private int victim;
public void lock() {
victim = i;
while (victim == i) {};
}
public void unlock() {}
}
Art of Multiprocessor
Programming
44
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
45
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
46
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
47
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
48
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
49
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
50
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
51
Peterson’s Algorithm
Announce I’m
interested
Defer to other
public void lock() {
flag[i] = true;
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
52
Peterson’s Algorithm
Announce I’m
interested
Defer to other
public void lock() {
flag[i] = true;
victim = i;
while (flag[j] && victim == i) {};
}
public void unlock() { Wait while other
flag[i] = false;
interested & I’m
}
the victim
No longer
interested
Art of Multiprocessor
Programming
53
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
54
• do código:
– writeA(flag[A]=true)  writeA(victim=A) 
readA(flag[B])  readA(victim) CSA
– writeB(flag[B]=true)  writeB(victim=B) 
readB(flag[A])  readB(victim) CSB
• vamos assumir:
– writeB(victim=B)  writeA(victim=A)
• como A entrou na RC:
• writeA(victim=A)  readA(flag[B] == false)
– mas então
• writeB(flag[B]=true)  writeB(victim=B) 
writeA(victim=A)  readA(flag[B] == false)
Art of Multiprocessor
Programming
55
Deadlock Free
public void lock() {
…
while (flag[j] && victim == i) {};
• Thread blocked
– only at while loop
– only if it is the victim
• One or the other must not be the victim
Art of Multiprocessor
Programming
56
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
57
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
58
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
59
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
60
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
61
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
62
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
63
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
64
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
65
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
66
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
67
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
68
From the Code
(1) writeB(level[B]=L)writeB(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) {};
}}
Art of Multiprocessor
Programming
69
From the Code
(2) writeA(victim[L]=A)readA(level[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) {};
}}
Art of Multiprocessor
Programming
70
By Assumption
(3) writeB(victim[L]=B)writeA(victim[L]=A)
By assumption, A is the last
thread to write victim[L]
Art of Multiprocessor
Programming
71
Combining Observations
(1) writeB(level[B]=L)writeB(victim[L]=B)
(3) writeB(victim[L]=B)writeA(victim[L]=A)
(2) writeA(victim[L]=A)readA(level[B])
Art of Multiprocessor
Programming
72
Combining Observations
(1) writeB(level[B]=L)writeB(victim[L]=B)
(3) writeB(victim[L]=B)writeA(victim[L]=A)
(2) writeA(victim[L]=A)readA(level[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) {};
Art of Multiprocessor
}}
Programming
73
Combining Observations
(1) writeB(level[B]=L)writeB(victim[L]=B)
(3) writeB(victim[L]=B)writeA(victim[L]=A)
(2) writeA(victim[L]=A)readA(level[B])
Thus, A read level[B] ≥ L,
A was last to write victim[L],
so it could not have entered level L!
Art of Multiprocessor
Programming
74
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
75
Bounded Waiting
• Want stronger fairness guarantees
• Thread not “overtaken” too much
• Need to adjust definitions ….
Art of Multiprocessor
Programming
76
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
77
r-Bounded Waiting
• For threads A and B:
– If DAk  DB j
• A’s k-th doorway precedes B’s j-th doorway
– Then CSAk  CSBj+r
• A’s k-th critical section precedes B’s (j+r)th critical section
• B cannot overtake A by more than r times
• First-come-first-served means r = 0.
Art of Multiprocessor
Programming
78
Fairness Again
• Filter Lock satisfies properties:
– No one starves
– But very weak fairness
• Not r-bounded for any r!
– That’s pretty lame…
Art of Multiprocessor
Programming
79
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
80
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
81
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
82
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
83
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
84
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
85
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
86
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
87
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
88
Bakery Algorithm
class Bakery implements Lock {
…
public void unlock() {
flag[i] = false;
}
}
Art of Multiprocessor
Programming
89
Bakery Algorithm
class Bakery implements Lock {
…
No longer
interested
public void unlock() {
flag[i] = false;
}
}
labels are always increasing
Art of Multiprocessor
Programming
90
No Deadlock
• There is always one thread with
earliest label
• Ties are impossible (why?)
Art of Multiprocessor
Programming
91
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
92
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
93
Mutual Exclusion
• Labels are strictly increasing so
• B must have seen flag[A] == false
Art of Multiprocessor
Programming
94
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
95
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
96
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
97
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
98
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
99
palavras de cautela
• esses algoritmos assumem coisas que
achamos intuitivas
– instruções em uma thread serão
executadas na ordem em que as
enxergamos
– ... mas compilador pode pensar
diferente...
Art of Multiprocessor
Programming
100
The Flag Example
y.read(0)
x.write(1)
y.write(1)
x.read(0)
time
Art of Multiprocessor
Programming
101
The Flag Example
y.read(0)
x.write(1)
y.write(1)
x.read(0)
• Each thread’s view is sequentially
consistent
time
– It went first
Art of Multiprocessor
Programming
102
The Flag Example
y.read(0)
x.write(1)
y.write(1)
x.read(0)
• Entire history isn’t sequentially
consistent
time
– Can’t both go first
Art of Multiprocessor
Programming
103
The Flag Example
y.read(0)
x.write(1)
y.write(1)
x.read(0)
• Is this behavior really so wrong?
– We can argue either way …
time
Art of Multiprocessor
Programming
104
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!
Art of Multiprocessor
Programming
105
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
Art of Multiprocessor
Programming
106
This work is licensed under a Creative Commons AttributionShareAlike 2.5 License.
• You are free:
– to Share — to copy, distribute and transmit the work
– to Remix — to adapt the work
• Under the following conditions:
– Attribution. You must attribute the work to “The Art of
Multiprocessor Programming” (but not in any way that
suggests that the authors endorse you or your use of the
work).
– Share Alike. If you alter, transform, or build upon this work,
you may distribute the resulting work only under the same,
similar or a compatible license.
• For any reuse or distribution, you must make clear to others the
license terms of this work. The best way to do this is with a link
to
– http://creativecommons.org/licenses/by-sa/3.0/.
• Any of the above conditions can be waived if you get permission
from the copyright holder.
• Nothing in this license impairs or restricts the author's moral
rights.
Art of Multiprocessor
Programming
107
Download