slides - University of Pennsylvania

advertisement
Foundations of Shared
Memory
Companion slides for
The Art of Multiprocessor Programming
by Maurice Herlihy & Nir Shavit
Modified by Rajeev Alur for
CIS 640 University of Pennsylvania
Fundamentals
• What is the weakest form of
communication that supports mutual
exclusion?
• What is the weakest shared object
that allows shared-memory
computation?
© 2007 Herlihy & Shavit
2
Alan Turing
• Helped us understand what is and is not
computable on a sequential machine.
• Still best model available
© 2007 Herlihy & Shavit
3
Turing Machine
Finite State
Controller
Reads and Writes
Infinite tape
1
0 1 1 0 1 0
© 2007 Herlihy & Shavit
4
Turing Computability
1
0 1 1 0 1 0
• Mathematical model of computation
• What is (and is not) computable
• Efficiency (mostly) irrelevant
© 2007 Herlihy & Shavit
5
Shared-Memory
Computability?
Shared Memory
10011
• Mathematical model of concurrent computation
• What is (and is not) concurrently computable
• Efficiency (mostly) irrelevant
© 2007 Herlihy & Shavit
6
Foundations of Shared Memory
To understand modern
multiprocessors we need to ask
some basic questions …
© 2007 Herlihy & Shavit
7
Foundations of Shared Memory
To understand modern
What is the weakest useful form of
multiprocessors we need to ask
shared memory?
some basic questions …
© 2007 Herlihy & Shavit
8
Foundations of Shared Memory
To understand modern
What is the weakest useful form of
multiprocessors
to ask
What we
canneed
it do?
shared memory?
some basic questions …
© 2007 Herlihy & Shavit
9
Foundations of Shared Memory
To understand modern
What is the weakest useful form of
multiprocessors
to ask
What we
canneed
it do?
shared
memory?
What
can’t it do?
some basic questions
…
© 2007 Herlihy & Shavit
10
Register *
Holds a
(binary) value
10011
* A memory location: name is historical
© 2007 Herlihy & Shavit
11
Register
Can be read
10011
10011
© 2007 Herlihy & Shavit
12
Register
Can be
written
01100
10011
© 2007 Herlihy & Shavit
13
Registers
public interface Register<T> {
public T read();
public void write(T v);
}
© 2007 Herlihy & Shavit
14
Registers
public interface Register<T> {
public T read();
public void write(T v);
}
Type of register
(usually Boolean or m-bit
Integer)
© 2007 Herlihy & Shavit
15
Single-Reader/Single-Writer
Register
10011
01100
10011
© 2007 Herlihy & Shavit
16
Multi-Reader/Single-Writer
Register
10011
01100
10011
© 2007 Herlihy & Shavit
17
Multi-Reader/Multi-Writer
Register
mumble
10011
mumble
mumble
10011
01010
10011
11011
© 2007 Herlihy & Shavit
18
Jargon Watch
• SRSW
– Single-reader single-writer
• MRSW
– Multi-reader single-writer
• MRMW
– Multi-reader multi-writer
© 2007 Herlihy & Shavit
19
Safe Register
OK if reads
and writes
don’t overlap
write(1001)
read(1001)
(2)
© 2007 Herlihy & Shavit
20
Safe Register
write(1001)
Some valid value if
reads and writes do
overlap
read(????)
0000
1001
© 2007 Herlihy & Shavit
$*&v
1111
21
Regular Register
write(0)
write(1)
read(1)
read(0)
• Single Writer
• Readers return:
– Old value if no overlap (safe)
– Old or one of new values if overlap
© 2007 Herlihy & Shavit
22
Regular or Not?
write(0)
write(1)
read(1)
read(0)
© 2007 Herlihy & Shavit
23
Regular or Not?
write(0)
write(1)
read(1)
read(0)
Overlap: returns new value
© 2007 Herlihy & Shavit
24
Regular or Not?
write(0)
write(1)
read(0)
Overlap: returns old value
© 2007 Herlihy & Shavit
25
Regular or Not?
write(0)
write(1)
read(1)
read(0)
© 2007 Herlihy & Shavit
26
Regular ≠ Linearizable
write(0)
write(1)
read(1)
read(0)
explain this!
write(1) already
happened
© 2007 Herlihy & Shavit
27
Atomic Register
write(1001)
write(1010)
read(1001)
read(1010)
read(1010)
Linearizable to sequential safe
register
© 2007 Herlihy & Shavit
28
Atomic Register
write(1001)
write(1010)
read(1001)
read(1010)
read(1010)
© 2007 Herlihy & Shavit
29
Register Space
MRMW
MRSW
SRSW
Safe
M-valued
Boolean
Regular
Atomic
© 2007 Herlihy & Shavit
30
Weakest Register
Single writer
1
Single reader
0 1
Safe Boolean register
© 2007 Herlihy & Shavit
31
Weakest Register
Single writer
Single reader
0 1 0
flipflop
0 1 0
Get correct reading if not during
state transition
© 2007 Herlihy & Shavit
32
Results
• From SRSW safe Boolean register
– All the other registers
– Mutual exclusion
• But not everything!
– Consensus hierarchy
(2)
© 2007 Herlihy & Shavit
33
Locking within Registers
• Not interesting to rely on mutual
exclusion in register constructions
• We want registers to implement
mutual exclusion!
• No fun to use mutual exclusion to
implement itself!
© 2007 Herlihy & Shavit
34
Wait-Free Implementations
Definition: An object implementation is
wait-free if every thread completes
a method in a finite number of steps
No mutual exclusion
– Thread could halt in critical section
– Build mutual exclusion from registers
© 2007 Herlihy & Shavit
35
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
36
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
Next
37
Register Names
public class SafeBoolMRSWRegister
implements Register<Boolean> {
public boolean read() { … }
public void write(boolean x) { … }
}
(3)
© 2007 Herlihy & Shavit
38
Register Names
public class SafeBoolMRSWRegister
implements Register<Boolean> {
public boolean read() { … }
public void write(boolean x) { … }
}
property
(3)
© 2007 Herlihy & Shavit
39
Register Names
public class SafeBoolMRSWRegister
implements Register<Boolean> {
public boolean read() { … }
public void write(boolean x) { … }
}
property
Size matters
(3)
© 2007 Herlihy & Shavit
40
Register Names
public class SafeBoolMRSWRegister
implements Register<Boolean> {
public boolean read() { … }
public void write(boolean x) { … }
}
property
type
(3)
How many readers
& writers?
© 2007 Herlihy & Shavit
41
Safe Boolean MRSW from
Safe Boolean SRSW
public class SafeBoolMRSWRegister
implements Register<Boolean> {
private SafeBoolSRSWRegister[] r =
new SafeBoolSRSWRegister[N];
public void write(boolean x) {
for (int j = 0; j < N; j++)
r[j].write(x);
}
public boolean read() {
int i = ThreadID.get();
return r[i].read();
}}
(2)
© 2007 Herlihy & Shavit
42
Safe Boolean MRSW from
Safe Boolean SRSW
public class SafeBoolMRSWRegister
implements BooleanRegister {
private SafeBoolSRSWRegister[] r =
new SafeBoolSRSWRegister[N];
public void write(boolean x) {
for (int j = 0; j < N; j++)
r[j].write(x);
}
public boolean read() {
int i = ThreadID.get();
return r[i].read(); Each thread
}}
has own
safe SRSW register
(2)
© 2007 Herlihy & Shavit
43
Safe Boolean MRSW from
Safe Boolean SRSW
public class SafeBoolMRSWRegister
implements BooleanRegister {
private SafeBoolSRSWRegister[] r =
new SafeBoolSRSWRegister[N];
public void write(boolean x) {
for (int j = 0; j < N; j++)
r[j].write(x);
}
public boolean read() {
int i = ThreadID.get();
return r[i].read();
write method
}}
(2)
© 2007 Herlihy & Shavit
44
Safe Boolean MRSW from
Safe Boolean SRSW
public class SafeBoolMRSWRegister
implements BooleanRegister {
private SafeBoolSRSWRegister[] r =
new SafeBoolSRSWRegister[N];
public void write(boolean x) {
for (int j = 0; j < N; j++)
r[j].write(x);
}
public boolean read() {
Write each
int i = ThreadID.get();
thread’s register
return r[i].read();
one at a time
}}
(2)
© 2007 Herlihy & Shavit
45
Safe Boolean MRSW from
Safe Boolean SRSW
public class SafeBoolMRSWRegister
implements BooleanRegister {
private SafeBoolSRSWRegister[] r =
new SafeBoolSRSWRegister[N];
public void write(boolean x) {
for (int j = 0; j < N; j++)
r[j].write(x);
read
}
public boolean read() {
int i = ThreadID.get();
return r[i].read();
}}
(2)
© 2007 Herlihy & Shavit
method
46
Safe Boolean MRSW from
Safe Boolean SRSW
public class SafeBoolMRSWRegister
implements BooleanRegister {
private SafeBoolSRSWRegister[] r =
new SafeBoolSRSWRegister[N];
public void write(boolean x) {
for (int j = 0; j < N; j++)
r[j].write(x);
}
public boolean read() {
int i = ThreadID.get();
return r[i].read();
}}
(2)
© 2007 Herlihy & Shavit
Read my own
register
47
Safe Boolean MRSW from
Safe Boolean SRSW
1
0
1
1
0
0
1
0 or 1
0
0
1
© 2007 Herlihy & Shavit
48
Q: Safe Multi-Valued MRSW
Safe Multi-Valued SRSW?
1
0
1
1011
1000
1011
Any value in range
0
1000
1000
© 2007 Herlihy & Shavit
49
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
Questions?
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
50
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
Next
51
Regular Boolean MRSW from
Safe Boolean MRSW
Safe register can
return 0 or 1
even if the same
value is written
1
1
0
© 2007 Herlihy & Shavit
Regular:
But
if only
it
changed,
old value
OKifto
read
not0 or
changed
1
52
Regular Boolean MRSW from
Safe Boolean MRSW
public class RegBoolMRSWRegister
implements Register<Boolean> {
private boolean old;
private SafeBoolMRSWRegister value;
public void write(boolean x) {
if (old != x) {
value.write(x);
old = x;
}}
public boolean read() {
return value.read();
}}
(2)
© 2007 Herlihy & Shavit
53
Regular Boolean MRSW from
Safe Boolean MRSW
public class RegBoolMRSWRegister
implements Register<Boolean> {
threadLocal boolean old;
private SafeBoolMRSWRegister value;
public void write(boolean x) {
if (old != x) {
value.write(x);
old = x;
Last bit this thread wrote
(OK, we’re cheating here on Java syntax)
}}
public boolean read() {
return value.read();
}}
(2)
© 2007 Herlihy & Shavit
54
Regular Boolean MRSW from
Safe Boolean MRSW
public class RegBoolMRSWRegister
implements Register<Boolean> {
threadLocal boolean old;
private SafeBoolMRSWRegister value;
public void write(boolean x) {
if (old != x) {
value.write(x);
old = x;
}}
public boolean read() {
return value.read();
Actual value
}}
(2)
© 2007 Herlihy & Shavit
55
Regular Boolean MRSW from
Safe Boolean MRSW
public class RegBoolMRSWRegister
implements Register<Boolean> {
threadLocal boolean old;
private SafeBoolMRSWRegister value;
public void write(boolean x) {
if (old != x) {
value.write(x);
Is new value different
old = x;
from last value I wrote?
}}
public boolean read() {
return value.read();
}}
(2)
© 2007 Herlihy & Shavit
56
Regular Boolean MRSW from
Safe Boolean MRSW
public class RegBoolMRSWRegister
implements Register<Boolean> {
threadLocal boolean old;
private SafeBoolMRSWRegister value;
public void write(boolean x) {
if (old != x) {
value.write(x);
old = x;
}}
public boolean read() {
If so, change it
return value.read();
}}
(otherwise don’t!)
(2)
© 2007 Herlihy & Shavit
57
Regular Boolean MRSW from
Safe Boolean MRSW
public class RegBoolMRSWRegister
implements Register<Boolean>{
threadLocal boolean old;
private SafeBoolMRSWRegister value;
public void write(boolean x) {
if (old != x) { •Overlap? No Overlap?
value.write(x);
•No problem
old = x;
•either Boolean value works
}}
public boolean read() {
return value.read();
}}
(2)
© 2007 Herlihy & Shavit
58
Regular Multi-Valued MRSW to
Safe Multi-Valued MRSW?
Safe register can return
value in range other than
old or new when value
changes
1
0101
© 2007 Herlihy & Shavit
1
Multivalued
Regular
register
can return
only old or
new when
value
changes!
59
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
Questions?
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
60
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
Next
61
MRSW Regular M-valued from
MRSW Regular Boolean
public class RegMRSWRegister implements Register{
RegBoolMRSWRegister[M] bit;
public void write(int x) {
this.bit[x].write(true);
for (int i=x-1; i>=0; i--)
this.bit[i].write(false);
}
public int read() {
for (int i=0; i < M; i++)
if (this.bit[i].read())
return i;
}}
© 2007 Herlihy & Shavit
62
MRSW Regular M-valued from
MRSW Regular Boolean
public class RegMRSWRegister implements Register{
RegBoolMRSWRegister[M] bit;
public void write(int x) {
this.bit[x].write(true);
for (int i=x-1; i>=0; i--)
this.bit[i].write(false);
}
Unary representation:
bit[i] means value i
public int read() {
for (int i=0; i < M; i++)
if (this.bit[i].read())
return i;
}}
© 2007 Herlihy & Shavit
63
MRSW Regular M-valued from
MRSW Regular Boolean
public class RegMRSWRegisterimplements Register {
RegBoolMRSWRegister[m] bit;
public void write(int x) {
this.bit[x].write(true);
for (int i=x-1; i>=0; i--)
this.bit[i].write(false);
}
public int read() {
for (int i=0; i < M; i++)
if (this.bit[i].read())
return i;
}}
(1)
© 2007 Herlihy & Shavit
Set bit x
64
MRSW Regular M-valued from
MRSW Regular Boolean
public class RegMRSWRegisterimplements Register {
RegBoolMRSWRegister[m] bit;
public void write(int x) {
this.bit[x].write(true);
for (int i=x-1; i>=0; i--)
this.bit[i].write(false);
}
public int read() {
for (int i=0; i < M; i++)
if (this.bit[i].read())
return i;
}}
(1)
Clear bits
from higher
to lower
© 2007 Herlihy & Shavit
65
MRSW Regular M-valued from
MRSW Regular Boolean
public class RegMRSWRegisterimplements Register {
RegBoolMRSWRegister[m] bit;
Scan from
public void write(int x) {
this.bit[x].write(true); to higher &
for (int i=x-1; i>=0; i--)
this.bit[i].write(false); first bit
}
lower
return
set
public int read() {
for (int i=0; i < M; i++)
if (this.bit[i].read())
return i;
}}
(1)
© 2007 Herlihy & Shavit
66
Writing M-Valued
Write 5
Initially 0
0
1 0 0 0 1
01234567
© 2007 Herlihy & Shavit
67
Writing M-Valued
Write 5
0
0
1 0 0 0 1
5
01234567
© 2007 Herlihy & Shavit
68
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
69
Road Map (Slight Detour)
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
SRSW Atomic
MRSW atomic
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
70
SRSW Atomic From SRSW
Regular
Regular writer
1234
5678
1234
Regular
reader
Instead of 5678…
When is this a
problem?
© 2007 Herlihy & Shavit
71
SRSW Atomic From SRSW
Regular
Regular writer
1234
5678
Initially
1234
5678
Regular
reader
Reg write(5678)
Reg read(5678)
time
© 2007 Herlihy & Shavit
72
SRSW Atomic From SRSW
Regular
Regular writer
1234
5678
Initially
1234
1234
Regular
reader
Instead of 5678…
Reg write(5678)
Reg read(1234)
time
© 2007 Herlihy & Shavit
73
SRSW Atomic From SRSW
Regular
Regular writer
1234
5678
Initially
1234
1234
Regular
reader
Instead of 5678…
Reg write(5678)
Reg read(5678)
Write
time 5678
happened
Reg read(1234)
© 2007 Herlihy & Shavit
74
Timestamped Values
1234
1:45
5678
2:00
Writer writes
value and stamp
together
© 2007 Herlihy & Shavit
2:00
5678
Reader saves last
reads (value,stamp)
and returns new
value only if higher
stamp
75
SRSW Atomic From SRSW
writer
Regular
reader
1:45
2:00
1:45
1234
1234
5678
Reg write(2:00 5678)
read(1:45 1234)
>
read(2:00 5678)
1:45 1234 Less
than 2:00 5678
So stick with
5678
time
old = 2:00 5678
© 2007 Herlihy & Shavit
76
Atomic Single Reader to
Atomic Multi-Reader
stamp
value
1:45
1:45
1:45
1:45
1234
1234
1234
1234
© 2007 Herlihy & Shavit
One per reader
77
Another Scenario
Writer starts
write…
stamp
value
2:00
1:45
1:45
1:45
5678
1234
1234
1234
© 2007 Herlihy & Shavit
78
Another Scenario
2:00, 5678
zzz…
stamp
value
2:00
1:45
1:45
1:45
5678
1234
1234
1234
reader
reads
later
reader
1:45
1234
Yellow was completely after blue but
read earlier value…not linearizable!
© 2007 Herlihy & Shavit
79
Multi-Reader Redux
One per thread
1
1:45
1:45
1:45
2
1234
1234
1234
1:45
1:45
1:45
3
1234
1234
1234
© 2007 Herlihy & Shavit
1:45
1:45
1:45
1234
1234
1234
1
2
3
80
Writer writes
column…
2:00, 5678
Multi-Reader Redux
reader
reads row
1
1
1:45
2:00
1:45
2:00
2:00
1:45
2
1234
5678
1234
5678
5678
1234
1:45
1:45
1:45
2
3
1234
1234
1234
© 2007 Herlihy & Shavit
1:45
1:45
1:45
1234
1234
1234
1
2
3
81
2:00, 5678
Multi-Reader Redux
zzz…after
second write
reader writes column to
1
notify others of what it
2
read
1
2
3
1:45
1234
1:45
1234
2:00
5678
1:45
1234 1
2:00
5678
1:45
1234
1:45
1234
2:00
5678
1:45
1234 2
2:00
5678
1:45
1234
2:00
1:45
5678
1234
1:45
1234 3
Yellow reader will read new
value in column written by
earlier Blue reader
© 2007 Herlihy & Shavit
82
Can’t Yellow Miss Blue’s
Update? … Only if Readers
Overlap…
1:45
1234
write(2:00 5678)
read(2:00 5678)
read(1:45 1234)
In which case
time
its OK to read
1234
© 2007 Herlihy & Shavit
83
Bad Case Only When Readers
Don’t Overlap
1:45
1234
write(2:00 5678)
read(2:00 5678)
In which case Blue
will complete writing
2:00 5678 to its
column
read(2:00 5678)
time
© 2007 Herlihy & Shavit
84
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
Next
MRMW atomic
Atomic snapshot
© 2007 Herlihy & Shavit
85
Multi-Writer Atomic From
Multi-Reader Atomic
Each writer
reads all
then writes
Max+1
to its register
stamp
value
1:45
1:45
2:00
1:45
2:15
1:45
1234
1234
5678
1234
XYZW
1234
Readers read all
and take max
(Lexicographic
like Bakery)
Max is 2:15,
return
XYZW
© 2007 Herlihy & Shavit
86
Atomic Execution
Means its Linearizable
write(1)
write(2)
Read (max = 1)
Read(max= 2)
write(4)
write(3)
write(2)
Read(max = 3)
Read(max = 4)
time
(4)
© 2007 Herlihy & Shavit
87
Linearization Points
write(1)
write(2)
Read (max = 1)
Read(max= 2)
write(4)
write(3)
write(2)
Read(max = 3)
Read(max = 4)
time
(4)
© 2007 Herlihy & Shavit
88
Linearization Points
Look at Writes
First
write(1)
write(2)
write(4)
write(3)
write(2)
time
(4)
© 2007 Herlihy & Shavit
89
Linearization Points
Order writes by
TimeStamp
write(1)
write(2)
write(4)
write(3)
write(2)
time
(4)
© 2007 Herlihy & Shavit
90
Linearization Points
Order reads by
max stamp read
write(1)
write(2)
Read (max = 1)
Read(max= 2)
write(4)
write(3)
write(2)
Read(max = 3)
Read(max = 4)
time
(4)
© 2007 Herlihy & Shavit
91
Linearization Points
Order reads by
max stamp read
write(1)
write(2)
Read (max = 1)
Read(max= 2)
write(4)
write(3)
write(2)
Read(max = 3)
Read(max = 4)
time
(4)
© 2007 Herlihy & Shavit
92
Linearization Points
The linearization point depends on the
execution (not a line in the code)!
write(1)
write(2)
Read (max = 1)
Read(max= 2)
write(4)
write(3)
write(2)
Read(max = 3)
Read(max = 4)
time
(4)
© 2007 Herlihy & Shavit
93
Road Map
•
•
•
•
•
•
•
SRSW safe Boolean
MRSW safe Boolean
MRSW regular Boolean
MRSW regular
MRSW atomic
MRMW atomic
Next
Atomic snapshot
© 2007 Herlihy & Shavit
94
Atomic Snapshot
update
© 2007 Herlihy & Shavit
scan
95
Atomic Snapshot
• Array of SWMR atomic registers
• Take instantaneous snapshot of all
• Generalizes to MRMW registers …
© 2007 Herlihy & Shavit
96
Snapshot Interface
public interface Snapshot {
public int update(int v);
public int[] scan();
}
(2)
© 2007 Herlihy & Shavit
97
Snapshot Interface
Thread i writes v to its register
public interface Snapshot {
public int update(int v);
public int[] scan();
}
(2)
© 2007 Herlihy & Shavit
98
Snapshot Interface
Instantaneous snapshot of all theads’
registers
public interface Snapshot {
public int update(int v);
public int[] scan();
}
(2)
© 2007 Herlihy & Shavit
99
Atomic Snapshot
• Collect
– Read values one at a time
• Problem
– Incompatible concurrent collects
– Result not linearizable
© 2007 Herlihy & Shavit
100
Clean Collects
• Clean Collect
– Collect during which nothing changed
– Can we make it happen?
– Can we detect it?
© 2007 Herlihy & Shavit
101
Simple Snapshot
• Put increasing labels on each entry
• Collect twice
• If both agree,
– We’re done
• Otherwise,
– Try again
Collect2
Collect1
1
1
22
1
22
1
7
=
7
13
13
18
12
18
12
© 2007 Herlihy & Shavit
102
Simple Snapshot: Update
public class SimpleSnapshot implements Snapshot {
private AtomicMRSWRegister[] register;
public void update(int value) {
int i = Thread.myIndex();
LabeledValue oldValue = register[i].read();
LabeledValue newValue =
new LabeledValue(oldValue.label+1, value);
register[i].write(newValue);
}
(1)
© 2007 Herlihy & Shavit
103
Simple Snapshot: Update
public class SimpleSnapshot implements Snapshot {
private AtomicMRSWRegister[] register;
public void update(int value) {
int i = Thread.myIndex();
LabeledValue oldValue = register[i].read();
LabeledValue newValue =
new LabeledValue(oldValue.label+1, value);
register[i].write(newValue);
}
One single-writer register per thread
(1)
© 2007 Herlihy & Shavit
104
Simple Snapshot: Update
public class SimpleSnapshot implements Snapshot {
private AtomicMRSWRegister[] register;
public void update(int value) {
int i = Thread.myIndex();
LabeledValue oldValue = register[i].read();
LabeledValue newValue =
new LabeledValue(oldValue.label+1, value);
register[i].write(newValue);
}
Write each time with higher label
(1)
© 2007 Herlihy & Shavit
105
Simple Snapshot: Collect
private LabeledValue[] collect() {
LabeledValue[] copy =
new LabeledValue[n];
for (int j = 0; j < n; j++)
copy[j] = this.register[j].read();
return copy;
}
(1)
© 2007 Herlihy & Shavit
106
Simple Snapshot
private LabeledValue[] collect() {
LabeledValue[] copy =
new LabeledValue[n];
for (int j = 0; j < n; j++)
copy[j] = this.register[j].read();
return copy;
}
Just read each register into array
(1)
© 2007 Herlihy & Shavit
107
Simple Snapshot: Scan
public int[] scan() {
LabeledValue[] oldCopy, newCopy;
oldCopy = collect();
collect: while (true) {
newCopy = collect();
if (!equals(oldCopy, newCopy)) {
oldCopy = newCopy;
continue collect;
}}
return getValues(newCopy);
}}}
(1)
© 2007 Herlihy & Shavit
108
Simple Snapshot: Scan
public int[] scan() {
LabeledValue[] oldCopy, newCopy; Collect
oldCopy = collect();
collect: while (true) {
newCopy = collect();
if (!equals(oldCopy, newCopy)) {
oldCopy = newCopy;
continue collect;
}}
return getValues(newCopy);
}}}
(1)
© 2007 Herlihy & Shavit
once
109
Simple Snapshot: Scan
public int[] scan() {
LabeledValue[] oldCopy, newCopy; Collect once
oldCopy = collect();
collect: while (true) {
Collect twice
newCopy = collect();
if (!equals(oldCopy, newCopy)) {
oldCopy = newCopy;
continue collect;
}}
return getValues(newCopy);
}}}
(1)
© 2007 Herlihy & Shavit
110
Simple Snapshot: Scan
public int[] scan() {
LabeledValue[] oldCopy, newCopy; Collect once
oldCopy = collect();
collect: while (true) {
Collect twice
newCopy = collect();
if (!equals(oldCopy, newCopy)) {
oldCopy = newCopy;
continue collect;
}}
On mismatch,
return getValues(newCopy);
try again
}}}
(1)
© 2007 Herlihy & Shavit
111
Simple Snapshot: Scan
public int[] scan() {
LabeledValue[] oldCopy, newCopy; Collect once
oldCopy = collect();
collect: while (true) {
Collect twice
newCopy = collect();
if (!equals(oldCopy, newCopy)) {
oldCopy = newCopy;
continue collect;
On match, return
}}
values
return getValues(newCopy);
}}}
(1)
© 2007 Herlihy & Shavit
112
Simple Snapshot
• Linearizable
• Update is wait-free
– No unbounded loops
• But Scan can starve
– If interrupted by concurrent update
© 2007 Herlihy & Shavit
113
Wait-Free Snapshot
• Add a scan before every update
• Write resulting snapshot together
with update value
• If scan is continuously interrupted by
updates, scan can take the update’s
snapshot
© 2007 Herlihy & Shavit
114
Wait-free Snapshot
If A’s scan observes that B moved
twice, then B completed an update
while A’s scan was in progress
Collect
Collect
Collect
26
24
12
26
24
12
26
24
12
B
≠
≠
Update
time
© 2007 Herlihy & Shavit
115
Wait-free Snapshot
A
Collect
Collect
Collect
26
24
12
26
24
12
26
24
12
B
≠
≠
Update
time
© 2007 Herlihy & Shavit
116
Wait-free Snapshot
A
Collect
Collect
Collect
26
24
12
26
24
12
26
24
12
B
≠
Scan
Update
≠
Write
time
© 2007 Herlihy & Shavit
117
Wait-free Snapshot
A
Collect
Collect
Collect
26
24
12
26
24
12
26
24
12
B
≠
Scan
Update
≠
Write
A can steal result of B’s scan
time
© 2007 Herlihy & Shavit
118
Once is not Enough
A
B
Scan
Update
Collect
Collect
26
24
12
26
24
12
≠
Write
Can A steal result of B’s scan?
time
© 2007 Herlihy & Shavit
119
Once is not Enough
A
B
Scan
Collect
26
24
12
26
24
12
≠
Write
Update
C
Collect
No
time
© 2007 Herlihy & Shavit
120
Someone Must Move Twice
Collect
Collect
Collect
26
24
12
26
24
12
26
24
12
B
≠
≠
Update
time
Why are scans wait-free?
© 2007 Herlihy & Shavit
121
Wait-Free Snapshot Label
public class SnapValue {
public int
label;
public int
value;
public int[] snap;
}
(2)
© 2007 Herlihy & Shavit
122
Wait-Free Snapshot Label
public class SnapValue {
public int
label;
public int
value;
public int[] snap;
}
Counter incremented
with each snapshot
(2)
© 2007 Herlihy & Shavit
123
Wait-Free Snapshot Label
public class SnapValue {
public int
label;
public int
value;
public int[] snap;
}
Actual value
(2)
© 2007 Herlihy & Shavit
124
Wait-Free Snapshot Label
public class SnapValue {
public int
label;
public int
value;
public int[] snap;
}
most recent snapshot
(2)
© 2007 Herlihy & Shavit
125
Wait-free Update
public void update(int value) {
int i = Thread.myIndex();
int[] snap = this.scan();
SnapValue oldValue = r[i].read();
SnapValue newValue =
new SnapValue(oldValue.label+1,
value, snap);
r[i].write(newValue);
}
(2)
© 2007 Herlihy & Shavit
126
Wait-free Scan
public void update(int value) {
Take scan
int i = Thread.myIndex();
int[] snap = this.scan();
SnapValue oldValue = r[i].read();
SnapValue newValue =
new SnapValue(oldValue.label+1,
value, snap);
r[i].write(newValue);
}
(2)
© 2007 Herlihy & Shavit
127
Wait-free Scan
public void update(int value) {
Take scan
int i = Thread.myIndex();
int[] snap = this.scan();
SnapValue oldValue = r[i].read();
SnapValue newValue =
new SnapValue(oldValue.label+1,
value, snap);
r[i].write(newValue);
Label value with scan
}
(2)
© 2007 Herlihy & Shavit
128
Wait-free Scan
public int[] scan() {
SnapValue[] oldCopy, newCopy;
boolean[] moved = new boolean[n];
oldCopy = collect();
collect: while (true) {
newCopy = collect();
for (int j = 0; j < n; j++) {
if (oldCopy[j].label != newCopy[j].label) {
…
Keep track of who moved
}}
return getValues(newCopy);
}}}
(2)
© 2007 Herlihy & Shavit
129
Wait-free Scan
public int[] scan() {
SnapValue[] oldCopy, newCopy;
boolean[] moved = new boolean[n];
oldCopy = collect();
collect: while (true) {
newCopy = collect();
for (int j = 0; j < n; j++) {
if (oldCopy[j].label != newCopy[j].label) {
…
}}
return getValues(newCopy);
}}}
Repeated double collect
(2)
© 2007 Herlihy & Shavit
130
Wait-free Scan
public int[] scan() {
SnapValue[] oldCopy, newCopy;
boolean[] moved = new boolean[n];
oldCopy = collect();
collect: while (true) {
newCopy = collect();
for (int j = 0; j < n; j++) {
if (oldCopy[j].label != newCopy[j].label) {
…
}}
return getValues(newCopy);
}}}
(2)
If mismatch detected…lets
expand
© 2007 Herlihy
& Shavit here…
131
Mismatch Detected
if (oldCopy[j].label != newCopy[j].label) {
if (moved[j]) {
// second move
return oldCopy[j].snap;
} else {
moved[j] = true;
oldCopy = newCopy;
continue collect;
}}}
return getValues(newCopy);
}}}
(2)
© 2007 Herlihy & Shavit
132
Mismatch Detected
if (oldCopy[j].label != newCopy[j].label) {
if (moved[j]) {
return oldCopy[j].snap;
} else {
moved[j] = true;
oldCopy = newCopy;
continue collect; If thread moved twice,
}}}
just steal its snapshot
return getValues(newCopy);
}}}
(2)
© 2007 Herlihy & Shavit
133
Mismatch Detected
if (oldCopy[j].label != newCopy[j].label) {
if (moved[j]) {
// second move
return oldCopy[j].snap;
} else {
moved[j] = true;
Remember that
oldCopy = newCopy;
thread moved
continue collect;
}}}
return getValues(newCopy);
}}}
(2)
© 2007 Herlihy & Shavit
134
Wait-free Scan
public int[] scan() {
SnapValue[] oldCopy, newCopy;
boolean[] moved = new boolean[n];
oldCopy = collect();
collect: while (true) {
newCopy = collect();
for (int j = 0; j < n; j++) {
if (oldCopy[j].label != newCopy[j].label) {
…
}}
return getValues(newCopy);
}}}
(2)
© 2007 Herlihy & Shavit
135
Wait-free
scan
At
most
n-1
depth
update
scan
update
scan
So some thread must
have had clean collect
© 2007 Herlihy & Shavit
136
Observations
• Uses unbounded counters
– can be replaced with 2 bits
• Assumes SWMR registers
– for labels
– can be extended to MRMW
© 2007 Herlihy & Shavit
137
Summary
• We saw we could implement MRMW
multi valued snapshot objects
• From SRSW binary safe registers
(simple flipflops)
• But what is the next step to attempt
with read-write registers?
© 2007 Herlihy & Shavit
138
Consensus: Each Thread has a
Private Input
19
32
21
© 2007 Herlihy & Shavit
139
They Communicate
© 2007 Herlihy & Shavit
140
They Agree on One Thread’s
Input
19
19
19
© 2007 Herlihy & Shavit
141
Formally: Consensus
• Consistent:
– all threads decide the same value
• Valid:
– the common decision value is some
thread's input
© 2007 Herlihy & Shavit
142
No Wait-Free Implementation
of Consensus using Registers
???
???
© 2007 Herlihy & Shavit
143
Formally
• Theorem
– There is no wait-free implementation of
n-thread consensus from read-write
registers
• Implication
– Asynchronous computability different
from Turing computability
© 2007 Herlihy & Shavit
144
Proof Strategy
• Assume otherwise
• Reason about the properties of any
such protocol
• Derive a contradiction
• Suffices to prove for binary
consensus and n=2
© 2007 Herlihy & Shavit
145
Wait-Free Computation
A moves
B moves
• Either A or B “moves”
• Moving means
– Register read
– Register write
© 2007 Herlihy & Shavit
146
The Two-Move Tree
Final
states
Initial
state
© 2007 Herlihy & Shavit
147
Decision Values
1
0
0
1
© 2007 Herlihy & Shavit
1
1
148
Bivalent: Both Possible
bivalent
1
0
0
1
© 2007 Herlihy & Shavit
1
1
149
Univalent: Single Value Possible
univalent
1
0
0
1
© 2007 Herlihy & Shavit
1
1
150
x-valent: x Only Possible
Decision
1-valent
1
0
0
1
© 2007 Herlihy & Shavit
1
1
151
Summary
• Wait-free computation is a tree
• Bivalent system states
– Outcome not fixed
• Univalent states
– Outcome is fixed
– May not be “known” yet
• 1-Valent and 0-Valent states
© 2007 Herlihy & Shavit
152
Claim
• Some initial state is bivalent
• Outcome depends on
– Chance
– Whim of the scheduler
…
• Lets prove it …
© 2007 Herlihy & Shavit
153
Both Inputs 0
0
0
Univalent: all executions must decide 0
© 2007 Herlihy & Shavit
154
Both Inputs 0
0
Including this solo execution by A
© 2007 Herlihy & Shavit
155
Both Inputs 1
1
1
All executions must decide 1
© 2007 Herlihy & Shavit
156
Both Inputs 1
1
Including this solo execution by B
© 2007 Herlihy & Shavit
157
What if inputs differ?
0
1
By Way of contradiction: If univalent
all executions must decide on same value
© 2007 Herlihy & Shavit
158
Critical States
critical
0-valent
1-valent
© 2007 Herlihy & Shavit
159
From a Critical State
c
0-valent
If A goes first,
protocol decides 0
1-valent
If B goes first,
protocol decides 1
© 2007 Herlihy & Shavit
160
Reaching Critical State
CB
CA
initially bivalent
univalent
CB
univalent
CA
univalent
c
univalent
0-valent
1-valent
© 2007 Herlihy & Shavit
161
Critical States
• Starting from a bivalent initial state
• The protocol can reach a critical
state
– Otherwise we could stay bivalent
forever
– And the protocol is not wait-free
© 2007 Herlihy & Shavit
162
Model Dependency
• So far, memory-independent!
• True for
–
–
–
–
Registers
Message-passing
Carrier pigeons
Any kind of asynchronous computation
© 2007 Herlihy & Shavit
163
Read-Write Memory
• Reads and/or writes
• To same/different registers
© 2007 Herlihy & Shavit
164
Completing the Proof
• Lets look at executions that:
– Start from a critical state
– Threads cause state to become univalent
by reading or writing to same/different
registers
– End within a finite number of steps
deciding either 0 or 1
• Show this leads to a contradiction
© 2007 Herlihy & Shavit
165
Possible Interactions
A reads x
A reads y
x.read()
y.read()
x.write() y.write()
x.read()
?
?
?
?
y.read()
?
?
?
?
x.write()
?
?
?
?
y.write()
?
?
?
?
© 2007 Herlihy & Shavit
166
Some Thread Reads
A runs solo,
eventually
decides 0
c
B reads x
0
1
States look
the same to A
© 2007 Herlihy & Shavit
A runs solo,
eventually
decides 1
167
Possible Interactions
x.read()
y.read()
x.write() y.write()
x.read()
no
no
no
no
y.read()
no
no
no
no
x.write()
no
no
?
?
y.write()
no
no
?
?
© 2007 Herlihy & Shavit
168
Writing Distinct Registers
A writes y
c
B writes x
A writes y
B writes x
0
1
Same story
© 2007 Herlihy & Shavit
169
Possible Interactions
x.read()
y.read()
x.write() y.write()
x.read()
no
no
no
no
y.read()
no
no
no
no
x.write()
no
no
?
no
y.write()
no
no
no
?
© 2007 Herlihy & Shavit
170
Writing Same Registers
A writes x
c
A runs solo,
eventually
decides 0
A writes x
0
States look
the same to A
B writes x
1
A runs solo,
eventually
decides 1
© 2007 Herlihy & Shavit
171
That’s All, Folks!
x.read()
y.read()
x.write() y.write()
x.read()
no
no
no
no
y.read()
no
no
no
no
x.write()
no
no
no
no
y.write()
no
no
no
no
© 2007 Herlihy & Shavit
172
Recap: Atomic Registers Can’t
Do Consensus
• If protocol exists
– It has a bivalent initial state
– Leading to a critical state
• What’s up with the critical state?
– Case analysis for each pair of methods
– As we showed, all lead to a contradiction
© 2007 Herlihy & Shavit
173
What Does Consensus have to
do with Concurrent Objects?
© 2007 Herlihy & Shavit
174
Consensus Object
public interface Consensus {
Object decide(object value);
}
© 2007 Herlihy & Shavit
175
Concurrent Consensus
Object
• We consider only one time objects:
– each thread calls method only once
• Linearizable to consensus object:
– Winner’s call went first
© 2007 Herlihy & Shavit
176
Generic Consensus Protocol
abstract class ConsensusProtocol<T>
implements Consensus {
protected T[] proposed = new T[N];
protected void propose(T value) {
proposed[ThreadID.get()] = value;
}
abstract public T decide(T value);
}
© 2007 Herlihy & Shavit
177
Generic Consensus Protocol
abstract class ConsensusProtocol<T>
implements Consensus {
protected T[] proposed = new T[N];
protected void propose(T value) {
proposed[ThreadID.get()] = value;
}
Each thread’s
proposed value
abstract public T decide(T value);
}
© 2007 Herlihy & Shavit
178
Generic Consensus Protocol
abstract class ConsensusProtocol<T>
implements Consensus {
protected T[] proposed = new T[N];
protected void propose(T value) {
proposed[ThreadID.get()] = value;
}
abstract public T decide(T value);
}
Propose a value
© 2007 Herlihy & Shavit
179
Generic Consensus Protocol
abstract
class
ConsensusProtocol<T>
Decide
a value:
abstract method
implements Consensus {
means subclass does the heavy lifting
protected T[] proposed = new T[N];
(real work)
protected void propose(T value) {
proposed[ThreadID.get()] = value;
}
abstract public T decide(T value);
}
© 2007 Herlihy & Shavit
180
Can a FIFO Queue
Implement Consensus?
© 2007 Herlihy & Shavit
181
FIFO Consensus
proposed array
FIFO Queue
with red and
black balls
8
Coveted red ball
Dreaded black ball
© 2007 Herlihy & Shavit
182
Protocol: Write Value to Array
0
0
© 2007 Herlihy & Shavit
1
183
Protocol: Take Next Item from
Queue
0
8
0
1
© 2007 Herlihy & Shavit
184
Protocol: Take Next Item from
Queue
I got the
0 coveted
1
red ball, so I will
decide my value
I got the dreaded
black ball, so I will
decide the other’s
value from the
array
8
© 2007 Herlihy & Shavit
185
Consensus Using FIFO Queue
public class QueueConsensus
extends ConsensusProtocol {
private Queue queue;
public QueueConsensus() {
queue = new Queue();
queue.enq(Ball.RED);
queue.enq(Ball.BLACK);
}
…
}
© 2007 Herlihy & Shavit
186
Initialize Queue
public class QueueConsensus
extends ConsensusProtocol {
private Queue queue;
public QueueConsensus() {
this.queue = new Queue();
this.queue.enq(Ball.RED);
this.queue.enq(Ball.BLACK);
}
…
}
8
© 2007 Herlihy & Shavit
187
Who Won?
public class QueueConsensus
extends ConsensusProtocol {
private Queue queue;
…
public decide(object value) {
propose(value);
Ball ball = this.queue.deq();
if (ball == Ball.RED)
return proposed[i];
else
return proposed[1-i];
}
}
© 2007 Herlihy & Shavit
188
Who Won?
public class QueueConsensus
extends ConsensusProtocol {
private Queue queue;
…
public decide(object value) {
propose(value);
Ball ball = this.queue.deq();
if (ball == Ball.RED)
return proposed[i];
else
return proposed[1-ij];
}
Race to dequeue
}
first queue item
© 2007 Herlihy & Shavit
189
Who Won?
public class QueueConsensus
extends ConsensusProtocol {
private Queue queue;
…
public decide(object value) {
propose(value);
Ball ball = this.queue.deq();
if (ball == Ball.RED)
return proposed[i];
else
return proposed[1-i];
i = ThreadID.get();
}
I win if I was
}
© 2007 Herlihy & Shavit
first
190
Who Won?
public class QueueConsensus
extends ConsensusProtocol {
private Queue queue;
Other thread wins if
…
I was{ second
public decide(object value)
propose(value);
Ball ball = this.queue.deq();
if (ball == Ball.RED)
return proposed[i];
else
return proposed[1-i];
}
}
© 2007 Herlihy & Shavit
191
Why does this Work?
•
•
•
•
If one thread gets the red ball
Then the other gets the black ball
Winner decides her own value
Loser can find winner’s value in array
– Because threads write array
before dequeueing from queue
© 2007 Herlihy & Shavit
192
Theorem
• We can solve 2-thread consensus
using only
– A two-dequeuer queue, and
– Some atomic registers
© 2007 Herlihy & Shavit
193
Implications
• Given
– A consensus protocol from queue and registers
• Assume there exists
– A queue implementation from atomic registers
• Substitution yields:
– A wait-free consensus protocol from atomic
registers
© 2007 Herlihy & Shavit
194
Corollary
• It is impossible to implement
– a two-dequeuer wait-free FIFO queue
– from read/write memory.
© 2007 Herlihy & Shavit
195
Consensus Numbers
• An object X has consensus number n
– If it can be used to solve n-thread
consensus
• Take any number of instances of X
• together with atomic read/write registers
• and implement n-thread consensus
– But not (n+1)-thread consensus
© 2007 Herlihy & Shavit
196
Consensus Numbers
• Theorem
– Atomic read/write registers have
consensus number 1
• Theorem
– Multi-dequeuer FIFO queues have
consensus number at least 2
© 2007 Herlihy & Shavit
197
Consensus Numbers Measure
Synchronization Power
• Theorem
– If you can implement X from Y
– And X has consensus number c
– Then Y has consensus number at least c
© 2007 Herlihy & Shavit
198
Synchronization Speed Limit
• Conversely
– If X has consensus number c
– And Y has consensus number d < c
– Then there is no way to construct a
wait-free implementation of X by Y
• This theorem will be very useful
– Unforeseen practical implications!
© 2007 Herlihy & Shavit
199
Challenge Problem
• Snapshot means
– Write any array element
– Read multiple array elements atomically
• What about
– Write multiple array elements atomically
– Scan any array elements
• Call this problem multiple assignment
© 2007 Herlihy & Shavit
200
Multiple Assignment Theorem
• Atomic registers cannot implement
multiple assignment
• Weird or what?
– Single write/multi read OK
– Multi write/multi read impossible
© 2007 Herlihy & Shavit
201
Proof Strategy
• If we can write to 2/3 array elements
– We can solve 2-consensus
– Impossible with atomic registers
• Therefore
– Cannot implement multiple assignment
with atomic registers
© 2007 Herlihy & Shavit
202 (1)
Proof Strategy
• Take a 3-element array
– A writes atomically to slots 0 and 1
– B writes atomically to slots 1 and 2
– Any thread can scan any set of locations
© 2007 Herlihy & Shavit
203
Double Assignment Interface
interface Assign2 {
public void assign(int i1, int v1,
int i2, int v2);
public int read(int i);
}
© 2007 Herlihy & Shavit
204
Double Assignment Interface
interface Assign2 {
public void assign(int i1, int v1,
int i2, int v2);
public int read(int i);
}
Atomically assign
value[i1]= v1
value[i2]= v2
© 2007 Herlihy & Shavit
205
Double Assignment Interface
interface Assign2 {
public void assign(int i1, int v1,
int i2, int v2);
public int read(int i);
}
Return i-th value
© 2007 Herlihy & Shavit
206
Initially
A
Writes to
0 and 1
B
Writes to
1 and 2
© 2007 Herlihy & Shavit
207
Thread A wins if
A
Thread B
didn’t move
B
© 2007 Herlihy & Shavit
208
Thread A wins if
A
Thread B
moved later
B
© 2007 Herlihy & Shavit
209
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
else
return proposed[j];
}}
© 2007 Herlihy & Shavit
210
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
Three slots
else
initialized to
return proposed[j];
EMPTY
}}
© 2007 Herlihy & Shavit
211
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
else
Assign id 0 to
return proposed[j];
entries 0,1 (or id 1
}}
to entries 1,2)
© 2007 Herlihy & Shavit
212
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
else
return proposed[j];
Read the register my
}}
thread didn’t assign
© 2007 Herlihy & Shavit
213
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
else
return proposed[j]; Other thread didn’t
move, so I win
}}
© 2007 Herlihy & Shavit
214
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
else
Other thread moved
return proposed[j]; later so I win
}}
© 2007 Herlihy & Shavit
215
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];
else
return proposed[j];
OK, I win.
}}
© 2007 Herlihy & Shavit
216
Multi-Consensus Code
class MultiConsensus extends …{
Assign2 a = new Assign2(3, EMPTY);
public Object decide(object value) {
a.assign(i, i, i+1, i);
int other = a.read((i+2) % 3);
if (other==EMPTY||other==a.read(1))
return proposed[i];(1)
else
return proposed[j];Other thread moved
}}
first, so I lose
© 2007 Herlihy & Shavit
217
Summary
• If a thread can assign atomically to 2
out of 3 array locations
• Then we can solve 2-consensus
• Therefore
– No wait-free multi-assignment
– From read/write registers
© 2007 Herlihy & Shavit
218
Read-Modify-Write Objects
• Method call
– Returns object’s prior value x
– Replaces x with mumble(x)
© 2007 Herlihy & Shavit
219
Read-Modify-Write
public abstract class RMWRegister {
private int value;
public int synchronized
getAndMumble() {
int prior = this.value;
this.value = mumble(this.value);
return prior;
}
}
© 2007 Herlihy & Shavit
220
Read-Modify-Write
public abstract class RMWRegister {
private int value;
public int synchronized
getAndMumble() {
int prior = this.value;
this.value = mumble(this.value);
return prior;
}
}
Return prior value
© 2007 Herlihy & Shavit
221
Read-Modify-Write
public abstract class RMWRegister {
private int value;
public int synchronized
getAndMumble() {
int prior = this.value;
this.value = mumble(this.value);
return prior;
}
}
Apply function to current value
© 2007 Herlihy & Shavit
222
RMW Everywhere!
• Most synchronization instructions
– are RMW methods
• The rest
– Can be trivially transformed into RMW
methods
© 2007 Herlihy & Shavit
223
Example: Read
public abstract class RMWRegister {
private int value;
public int synchronized read() {
int prior = this.value;
this.value = this.value;
return prior;
}
}
© 2007 Herlihy & Shavit
224
Example: Read
public abstract class RMW {
private int value;
public int synchronized read() {
int prior = this.value;
this.value = this.value;
return prior;
}
}
Apply f(v)=v, the
identity function
© 2007 Herlihy & Shavit
225
Example: getAndSet
public abstract class RMWRegister {
private int value;
public int synchronized
getAndSet(int v) {
int prior = this.value;
this.value = v;
return prior;
}
…
}
© 2007 Herlihy & Shavit
226
Example: getAndSet (swap)
public abstract class RMWRegister {
private int value;
public int synchronized
getAndSet(int v) {
int prior = this.value;
this.value = v;
return prior;
}
F(x)=v is constant function
…
}
© 2007 Herlihy & Shavit
227
getAndIncrement
public abstract class RMWRegister {
private int value;
public int synchronized
getAndIncrement() {
int prior = this.value;
this.value = this.value + 1;
return prior;
}
…
}
© 2007 Herlihy & Shavit
228
getAndIncrement
public abstract class RMWRegister {
private int value;
public int synchronized
getAndIncrement() {
int prior = this.value;
this.value = this.value + 1;
return prior;
}
…
F(x) = x+1
}
(1)
© 2007 Herlihy & Shavit
229
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
return false;
} … }
© 2007 Herlihy & Shavit
230
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
return false;
If value is what was
} … }
expected, …
© 2007 Herlihy & Shavit
231
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
return false;
… replace it
} … }
© 2007 Herlihy & Shavit
232
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
return false;
Report success
} … }
© 2007 Herlihy & Shavit
233
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
Otherwise report
return false;
failure
} … }
© 2007 Herlihy & Shavit
234
Read-Modify-Write
public abstract class RMWRegister {
private int value;
public void synchronized
getAndMumble() {
int prior = this.value;
this.value = mumble(this.value);
return prior;
}
}
Lets characterize F(x)…
© 2007 Herlihy & Shavit
235
Definition
• A RMW method
– With function mumble(x)
– is non-trivial if there exists a value v
– Such that v ≠ mumble(v)
© 2007 Herlihy & Shavit
236
Par Example
• Identity(x) = x
– is trivial
• getAndIncrement(x) = x+1
– is non-trivial
© 2007 Herlihy & Shavit
237
Theorem
• Any non-trivial RMW object has
consensus number at least 2
• No wait-free implementation of RMW
registers from atomic registers
• Hardware RMW instructions not just
a convenience
© 2007 Herlihy & Shavit
238
Proof
public class RMWConsensus
extends ConsensusProtocol {
private RMWRegister r = v;
public Object decide(object value) {
propose(value);
if (r.getAndMumble() == v)
return proposed[i];
else
return proposed[j];
}}
© 2007 Herlihy & Shavit
239
Proof
public class RMWConsensus
extends ConsensusProtocol {
private RMWRegister r = v;
public Object decide(object value) {
propose(value);
if (r.getAndMumble() == v)
return proposed[i];
Initialized to v
else
return proposed[j];
}}
© 2007 Herlihy & Shavit
240
Proof
public class RMWConsensus
extends Consensus {
Am I first?
private RMWRegister r = v;
public Object decide(object value) {
if (r.getAndMumble() == v)
return proposed[i];
else
return proposed[j];
}}
© 2007 Herlihy & Shavit
241
Proof
public class RMWConsensus
extends ConsensusProtocol {
private RMWRegister r = v;
public Object decide(object value) {
Yes, return
propose(value);
if (r.getAndMumble() == v) my input
return proposed[i];
else
return proposed[j];
}}
© 2007 Herlihy & Shavit
242
Proof
public class RMWConsensus
extends ConsensusProtocol {
private RMWRegister r = v;
public Object decide(object value) {
propose(value);
if (r.getAndMumble() == v)
No, return
return proposed[i];
other’s input
else
return proposed[j];
}}
(4)
© 2007 Herlihy & Shavit
243
Proof
• We have displayed
– A two-thread consensus protocol
– Using any non-trivial RMW object
© 2007 Herlihy & Shavit
244
Interfering RMW
• Let F be a set of functions such that
for all fi and fj, either
– Commute: fi(fj(v))=fj(fi(v))
– Overwrite: fi(fj(v))=fi(v)
• Claim: Any set of RMW objects that
commutes or overwrites has
consensus number exactly 2
© 2007 Herlihy & Shavit
245
Examples
• “test-and-set” getAndSet(1) f(v)=1
Overwrite fi(fj(v))=fi(v)
• “swap” getAndSet(x) f(v,x)=x
Overwrite fi(fj(v))=fi(v)
• “fetch-and-inc” getAndIncrement() f(v)=v+1
Commute fi(fj(v))= fj(fi(v))
© 2007 Herlihy & Shavit
246
Meanwhile Back at the Critical
State
A about to
apply fA
B about to
apply fB
c
0-valent
1-valent
© 2007 Herlihy & Shavit
247
Maybe the Functions Commute
A applies fA
c
B applies fB
B applies fB
A applies fA
C runs solo
C runs solo
0-valent
0
1
© 2007 Herlihy & Shavit
1-valent
248
Maybe the Functions Commute
A applies fA
c
B applies fB
These states look the same to C
B applies fB
A applies fA
C runs solo
C runs solo
0-valent
0
1
© 2007 Herlihy & Shavit
1-valent
249
Maybe the Functions Overwrite
A applies fA
c
B applies fB
A applies fA
C runs solo
0
C runs solo
1
0-valent
© 2007 Herlihy & Shavit
1-valent
250
Maybe the Functions Overwrite
These states look the same to C
A applies fA
c
B applies fB
A applies fA
C runs solo
0
C runs solo
1
0-valent
© 2007 Herlihy & Shavit
1-valent
251
Impact
• Many early machines provided these
“weak” RMW instructions
– Test-and-set (IBM 360)
– Fetch-and-add (NYU Ultracomputer)
– Swap (Original SPARCs)
• We now understand their limitations
– But why do we want consensus anyway?
© 2007 Herlihy & Shavit
252
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
return false;
} … }
© 2007 Herlihy & Shavit
253
compareAndSet
public abstract class RMWRegister {
private int value;
public boolean synchronized
compareAndSet(int expected,
int update) {
int prior = this.value;
if (this.value==expected) {
this.value = update; return true;
}
return false;
replace value if its what we
} … }
expected, …
© 2007 Herlihy & Shavit
254
compareAndSet Has ∞
Consensus Number
public class RMWConsensus
extends ConsensusProtocol {
private AtomicInteger r =
new AtomicInteger(-1);
public Object decide(object value) {
propose(value);
r.compareAndSet(-1,i);
return proposed[r.get()];
}
}
© 2007 Herlihy & Shavit
255
compareAndSet Has ∞
Consensus Number
public class RMWConsensus
extends ConsensusProtocol {
private AtomicInteger r =
new AtomicInteger(-1);
public Object decide(object value) {
propose(value)
r.compareAndSet(-1,i);
return proposed[r.get()];
}
}
Initialized to -1
© 2007 Herlihy & Shavit
256
compareAndSet Has ∞
Consensus Number
public class RMWConsensus
extends ConsensusProtocol {
private AtomicInteger Try
r = to swap in
new AtomicInteger(-1); my id
public Object decide(object value) {
propose(value);
r.compareAndSet(-1,i);
return proposed[r.get()];
}
}
© 2007 Herlihy & Shavit
257
compareAndSet Has ∞
Consensus Number
public class RMWConsensus
extends ConsensusProtocol {
winner’s
private AtomicInteger Decide
r =
new AtomicInteger(-1);preference
public Object decide(object value) {
propose(value);
r.compareAndSet(-1,i);
return proposed[r.get()];
}
}
© 2007 Herlihy & Shavit
258
The Consensus Hierarchy
1 Read/Write Registers, Snapshots…
2 getAndSet, getAndIncrement, …
.
.
.
∞
compareAndSet,…
© 2007 Herlihy & Shavit
259
Multiple Assignment
• Atomic k-assignment
• Solves consensus for 2k-2 threads
• Every even consensus number has an
object (can be extended to odd numbers)
© 2007 Herlihy & Shavit
260
Download