universality of consensuscs.brown.edu/courses/cs176/lectures/chapter_06.pdf · 2018. 10. 4. ·...
TRANSCRIPT
Universality of Consensus
Companion slides for
The Art of Multiprocessor Programming
by Maurice Herlihy & Nir Shavit
Turing Computability
• A mathematical model of computation
• Computable = Computable on a T-Machine
0 1 1 0 1 01
2Art of Multiprocessor Programming
Shared-Memory Computability
• Model of asynchronous concurrent
computation
• Computable = Wait-free/Lock-free
computable on a multiprocessor
cache
shared memory
cachecache
3Art of Multiprocessor Programming
Consensus Hierarchy
1 Read/Write Registers, Snapshots…
2 getAndSet, getAndIncrement, …
∞ compareAndSet,…
.
.
.
4Art of Multiprocessor Programming
Who Implements Whom?
1 Read/Write Registers, Snapshots…
2 getAndSet, getAndIncrement, …
∞ compareAndSet,…
.
.
.
no
no
no
5Art of Multiprocessor Programming
Hypothesis
1 Read/Write Registers, Snapshots…
2 getAndSet, getAndIncrement, …
∞ compareAndSet,…
.
.
.
yes?
yes?
yes?
6Art of Multiprocessor Programming
Theorem: Universality
• Consensus is universal
• From n-thread consensus build a
– Wait-free
– Linearizable
– n-threaded implementation
– Of any sequentially specified object
7Art of Multiprocessor Programming
Proof Outline
• A universal construction
– From n-consensus objects
– And atomic registers
• Any wait-free linearizable object
– Not a practical construction
– But we know where to start looking …
8Art of Multiprocessor Programming
Like a Turing Machine
• This construction
– Illustrates what needs to be done
– Optimization fodder
• Correctness, not efficiency
– Why does it work? (Asks the scientist)
– How does it work? (Asks the engineer)– Would you like fries with that? (Asks the liberal arts major)
9Art of Multiprocessor Programming
A Generic Sequential Object
public interface SeqObject {
public abstract
Response apply(Invocation invoc);
}
10Art of Multiprocessor Programming
A Generic Sequential Object
public interface SeqObject {
public abstract
Response apply(Invocation invoc);
}
Push:5, Pop:null
11Art of Multiprocessor Programming
Invocationpublic class Invoc {
public String method;
public Object[] args;
}
12Art of Multiprocessor Programming
Invocationpublic class Invoc {
public String method;
public Object[] args;
}
Method name
13Art of Multiprocessor Programming
Invocationpublic class Invoc {
public String method;
public Object[] args;
}
Arguments
14Art of Multiprocessor Programming
A Generic Sequential Object
public interface SeqObject {
public abstract
Response apply(Invocation invoc);
}
15Art of Multiprocessor Programming
A Generic Sequential Object
public interface SeqObject {
public abstract
Response apply(Invocation invoc);
}
OK, 4
16Art of Multiprocessor Programming
Responsepublic class Response {
public Object value;
}
17Art of Multiprocessor Programming
Responsepublic class Response {
public Object value;
}
Return value
18Art of Multiprocessor Programming
19
Universal Concurrent Object
public interface SeqObject {
public abstract
Response apply(Invocation invoc);
}
A universal concurrent object is
linearizable to the generic
sequential object
19Art of Multiprocessor Programming
Start with Lock-Free Universal
Construction
• First Lock-free: infinitely often some
method call finishes.
• Then Wait-Free: each method call
takes a finite number of steps to finish
20Art of Multiprocessor Programming
Naïve Idea
• Consensus object stores reference to
cell with current state
• Each thread creates new cell
– computes outcome,
– tries to switch pointer to its outcome
• Sadly, no …
– consensus objects can be used once only
21Art of Multiprocessor Programming
Naïve Idea
enq
deq
22Art of Multiprocessor Programming
head
Naïve Idea
deq
Concurrent
Object
?
enq
Decide which
to apply using
consensus
23Art of Multiprocessor Programming
Once is not Enough?
public T decide(T value) {
propose(value);
Ball ball = queue.deq();
if (ball == Ball.RED)
return proposed[i];
else
return proposed[1-i];
}
Solved one-shot 2-consensus.
Not clear how to reuse or reread …
Queue based
consensus
24Art of Multiprocessor Programming
Improved Idea: Linked-List
Representation
enqenqenqtail
deq
Each node contains a fresh
consensus object used to
decide on next operation
25Art of Multiprocessor Programming
Universal Construction
• Object represented as
– Initial Object State
– A Log: a linked list of the method calls
26Art of Multiprocessor Programming
Universal Construction
• Object represented as
– Initial Object State
– A Log: a linked list of the method calls
• New method call
– Find end of list
– Atomically append call
– Compute response by replaying log
27Art of Multiprocessor Programming
Basic Idea
• Use one-time consensus object to decide next pointer
28Art of Multiprocessor Programming
Basic Idea
• Use one-time consensus object to decide next pointer
• All threads update actual next pointer based on decision
– OK because they all write the same value
29Art of Multiprocessor Programming
Basic Idea
• Threads use one-time consensus object to decide which node goes next
• Threads update actual next field to reflect consensus outcome
– OK because they all write the same value
• Challenges
– Lock-free means we need to worry what happens if a thread stops in the middle
30Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
31Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
Standard interface for class whose
objects are totally ordered
32Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
the invocation
33Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
Decide on next node
(next method applied to object)
34Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
Traversable pointer to next node
(needed because you cannot
repeatedly read a consensus object) 35Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
Seq number
36Art of Multiprocessor Programming
public class Node implements
java.lang.Comparable {
public Invoc invoc;
public Consensus<Node> decideNext;
public Node next;
public int seq;
public Node(Invoc invoc) {
invoc = invoc;
decideNext = new Consensus<Node>()
seq = 0;
}
Basic Data Structures
Create new node for this method
invocation
37Art of Multiprocessor Programming
Universal Object
head
1 2 3
decideNext
(Consensus
Object)
Ptr to cell
w/highest Seq
Num
Seq number,
Invoc
tail
node
next
4
38Art of Multiprocessor Programming
Universal Object
head
1 2 3All threads
repeatedly
modify
head…back to
where we
started?
tail
node
4
39Art of Multiprocessor Programming
…
The Solution
head
1 2 3
tail
node
i
4
Make head
an array
Ref to
node at
frontThread i
updates
location i
Find head by
finding Max of
nodes referenced
by head array
40Art of Multiprocessor Programming
Universal Object
public class Universal {
private Node[] head;
private Node tail = new Node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail
}
41Art of Multiprocessor Programming
Universal Object
public class Universal {
private Node[] head;
private Node tail = new Node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail
}
Head Pointers Array
42Art of Multiprocessor Programming
Universal Object
public class Universal {
private Node[] head;
private Node tail = new Node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail
}
Tail is a sentinel node with
sequence number 1
43Art of Multiprocessor Programming
Universal Object
public class Universal {
private Node[] head;
private Node tail = new Node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail
}
Initially head points to tail
44Art of Multiprocessor Programming
public static Node max(Node[] array) {
Node max = array[0];
for (int i = 1; i < array.length; i++)
if (max.seq < array[i].seq)
max = array[i];
return max;
}
Find Max Head Value
45Art of Multiprocessor Programming
public static Node max(Node[] array) {
Node max = array[0];
for (int i = 0; i < array.length; i++)
if (max.seq < array[i].seq)
max = array[i];
return max;
}
Find Max Head Value
Traverse
the array
46Art of Multiprocessor Programming
public static Node max(Node[] array) {
Node max = array[0];
for (int i = 0; i < array.length; i++)
if (max.seq < array[i].seq)
max = array[i];
return max;
}
Find Max Head Value
Compare the seq nums of nodes
pointed to by the array
47Art of Multiprocessor Programming
public static Node max(Node[] array) {
Node max = array[0];
for (int i = 0; i < array.length; i++)
if (max.seq < array[i].seq)
max = array[i];
return max;
}
Find Max Head Value
Return node with maximal sequence
number
48Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
49Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
Apply has invocation as input and
returns the appropriate response
50Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
my ID
51Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
My method call
52Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
As long as I have not been
threaded into list
53Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
Head of list to which we
will try to append
54Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
}
Propose next node
55Art of Multiprocessor Programming
Universal Application
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
}
Set next field to consensus winner
56Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
Set seq number
(indicating node was appended)
57Art of Multiprocessor Programming
Universal Application Part I
public Response apply(Invoc invoc) {
int i = ThreadID.get();
Node prefer = new node(invoc);
while (prefer.seq == 0) {
Node before = Node.max(head);
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
…
add to head array so new
head will be found
58Art of Multiprocessor Programming
Part 2 – Compute Response
null enq( )
tail
Red’s
method call
…deq()enq( )
return Private copy of object
59Art of Multiprocessor Programming
Universal Application Part 2
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
60Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
Compute result by sequentially applying
method calls in list to a private copy
61Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
Start with copy of sequential object
62Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
new method call appended after tail
63Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
While my method call not linked …
64Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
Apply current node’s method
65Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
Return result after my method call applied
66Art of Multiprocessor Programming
Correctness
• List defines linearized sequential
history
• Thread returns its response based on
list order
67Art of Multiprocessor Programming
68
Lock-freedom
• Lock-free because
– A thread moves forward in list
– Can repeatedly fail to win consensus on
“real” head only if another succeeds
– Consensus winner adds node and
completes within a finite number of steps
68Art of Multiprocessor Programming
Wait-free Construction
• Lock-free construction + announce
array
• Stores (pointer to) node in announce
– If a thread doesn’t append its node
– Another thread will see it in array and help
append it
69Art of Multiprocessor Programming
Helping
• “Announcing” my intention
– Guarantees progress
– Even if the scheduler hates me
– My method call will complete
• Makes protocol wait-free
• Otherwise starvation possible
70Art of Multiprocessor Programming
…
…
Wait-free Construction
head
1 2 3
tail i
4
announce
Ref to cell thread i
wants to append
i
71Art of Multiprocessor Programming
public class Universal {
private Node[] announce;
private Node[] head;
private Node tail = new node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail; announce[j] = tail
};
The Announce Array
72Art of Multiprocessor Programming
public class Universal {
private Node[] announce;
private Node[] head;
private Node tail = new node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail; announce[j] = tail
};
The Announce Array
New field: announce array
73Art of Multiprocessor Programming
public class Universal {
private Node[] announce;
private Node[] head;
private Node tail = new node();
tail.seq = 1;
for (int j=0; j < n; j++){
head[j] = tail; announce[j] = tail
};
The Announce Array
All entries initially point to tail
74Art of Multiprocessor Programming
public Response apply(Invoc invoc) {
int i = ThreadID.get();
announce[i] = new Node(invoc);
head[i] = Node.max(head);
while (announce[i].seq == 0) {
…
// while node not appended to list
…
}
A Cry For Help
75Art of Multiprocessor Programming
public Response apply(Invoc invoc) {
int i = ThreadID.get();
announce[i] = new Node(invoc);
head[i] = Node.max(head);
while (announce[i].seq == 0) {
…
// while node not appended to list
…
}
A Cry For Help
Announce new method call,
asking help from others
76Art of Multiprocessor Programming
public Response apply(Invoc invoc) {
int i = ThreadID.get();
announce[i] = new Node(invoc);
head[i] = Node.max(head);
while (announce[i].seq == 0) {
…
// while node not appended to list
…
}
A Cry For Help
Look for end of list
77Art of Multiprocessor Programming
public Response apply(Invoc invoc) {
int i = ThreadID.get();
announce[i] = new Node(invoc);
head[i] = Node.max(head);
while (announce[i].seq == 0) {
…
// while node not appended to list
…
}
A Cry For Help
Main loop, while node not appended
(either by me or helper)
78Art of Multiprocessor Programming
Main Loop
• Non-zero sequence # means success
79Art of Multiprocessor Programming
Main Loop
• Non-zero sequence # means success
• Thread keeps helping append nodes
80Art of Multiprocessor Programming
Main Loop
• Non-zero sequence # means success
• Thread keeps helping append nodes
• Until its own node is appended
81Art of Multiprocessor Programming
while (announce[i].seq == 0) {
Node before = head[i];
Node help = announce[(before.seq + 1) % n];
if (help.seq == 0)
prefer = help;
else
prefer = announce[i];
…
Main Loop
82Art of Multiprocessor Programming
while (announce[i].seq == 0) {
Node before = head[i];
Node help = announce[(before.seq + 1) % n];
if (help.seq == 0)
prefer = help;
else
prefer = announce[i];
…
Main Loop
Keep trying until my cell gets a
sequence number
83Art of Multiprocessor Programming
while (announce[i].seq == 0) {
Node before = head[i];
Node help = announce[(before.seq + 1) % n];
if (help.seq == 0)
prefer = help;
else
prefer = announce[i];
…
Main Loop
Possible end of list
84Art of Multiprocessor Programming
while (announce[i].seq == 0) {
Node before = head[i];
Node help = announce[(before.seq + 1) % n];
if (help.seq == 0)
prefer = help;
else
prefer = announce[i];
…
Main Loop
Whom do I help?
85Art of Multiprocessor Programming
Altruism
• Choose a thread to “help”
86Art of Multiprocessor Programming
Altruism
• Choose a thread to “help”
• If that thread needs help
– Try to append its node
– Otherwise append your own
87Art of Multiprocessor Programming
Altruism
• Choose a thread to “help”
• If that thread needs help
– Try to append its node
– Otherwise append your own
• Worst case
– Everyone tries to help same pitiful loser
– Someone succeeds
88Art of Multiprocessor Programming
Help!
• When last node in list has
sequence number k
89Art of Multiprocessor Programming
Help!
• When last node in list has
sequence number k
• All threads check …
– Whether thread k+1 mod n wants
help
– If so, try to append her node first
90Art of Multiprocessor Programming
Help!
• First time after thread k+1 announces
– No guarantees
91Art of Multiprocessor Programming
Help!
• First time after thread k+1 announces
– No guarantees
• After n more nodes appended
– Everyone sees that thread k+1 wants help
– Everyone tries to append that node
– Someone succeeds
92Art of Multiprocessor Programming
Sliding Window Lemma
• After thread A announces its node
• No more than n other calls
– Can start and finish
– Without appending A’s node
93Art of Multiprocessor Programming
Helping
head
1 2 3
Max head
+1 = n+4
n+2 n+3…
announce
Thread 4:
Help me!
4
So all see
and help
append 4
tail
94Art of Multiprocessor Programming
The Sliding Help Window
head
…
announce
4
tail
help 3 help 43
95Art of Multiprocessor Programming
1 2 3 n+2 n+3
while (announce[i].seq == 0) {
Node before = head[i];
Node help = announce[(before.seq + 1) % n];
if (help.seq == 0)
prefer = help;
else
prefer = announce[i];
…
Sliding Help Window
In each main loop iteration pick
another thread to help
96Art of Multiprocessor Programming
while (announce[i].seq == 0) {
Node before = head[i];
Node help = announce[(before.seq + 1) % n];
if (help.seq == 0)
prefer = help;
else
prefer = announce[i];
…
Sliding Help WindowHelp if help required, but
otherwise it’s all about me!
97Art of Multiprocessor Programming
Rest is Same as Lock-free
while (announce[i].seq == 0) {
…
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
98Art of Multiprocessor Programming
Rest is Same as Lock-free
while (announce[i].seq == 0) {
…
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}Call consensus to attempt to append
99Art of Multiprocessor Programming
Rest is Same as Lock-free
while (announce[i].seq == 0) {
…
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
cache consensus result for later use
100Art of Multiprocessor Programming
Rest is Same as Lock-free
while (announce[i].seq == 0) { …
Node after =
before.decideNext.decide(prefer);
before.next = after;
after.seq = before.seq + 1;
head[i] = after;
}
Tell world that node is appended
101Art of Multiprocessor Programming
Finishing the Job
• Once thread’s node is linked …
102Art of Multiprocessor Programming
Finishing the Job
• Once thread’s node is linked…
• The rest same as lock-free algorithm
103Art of Multiprocessor Programming
Finishing the Job
• Once thread’s node is linked …
• The rest same as lock-free algorithm
• Compute result by
– sequentially applying list’s method calls
– to a private copy of the object
– starting from the initial state
104Art of Multiprocessor Programming
Then Same Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != announce[i]){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
105Art of Multiprocessor Programming
Universal Application Part II
...
//compute my response
SeqObject MyObject = new SeqObject();
current = tail.next;
while (current != prefer){
MyObject.apply(current.invoc);
current = current.next;
}
return MyObject.apply(current.invoc);
}
Return result after applying my method
106Art of Multiprocessor Programming
Shared-Memory Computability
Wait-free/Lock-free computable
=
Solving n-consensus
10011Universal
Construction
107Art of Multiprocessor Programming
public class RMWRegister {
private int value;
public boolean getAndSet(int update)
{
int prior = value;
value = update;
return prior;
}
}
Swap (getAndSet) not Universal
108Art of Multiprocessor Programming
public class RMWRegister {
private int value;
public boolean getAndSet(int update)
{
int prior = value;
value = update;
return prior;
}
}Consensus number 2
Swap (getAndSet) not Universal
109Art of Multiprocessor Programming
public class RMWRegister {
private int value;
public boolean getAndSet(int update)
{
int prior = value;
value = update;
return prior;
}
}Not universal for ≥3 threads
Swap (getAndSet) not Universal
110Art of Multiprocessor Programming
public class RMWRegister {
private int value;
public boolean
compareAndSet(int expected,
int update) {
int prior = value;
if (value == expected) {
value = update;
return true;
}
return false;
}}
CompareAndSet is Universal
111Art of Multiprocessor Programming
public class RMWRegister {
private int value;
public boolean
compareAndSet(int expected,
int update) {
int prior = value;
if (value == expected) {
value = update;
return true;
}
return false;
}}
CompareAndSet is Universal
Consensus number ∞
112Art of Multiprocessor Programming
public class RMWRegister {
private int value;
public boolean
compareAndSet(int expected,
int update) {
int prior = value;
if (value == expected) {
value = update;
return true;
}
return false;
}}
CompareAndSet is Universal
Universal for any number of threads
113Art of Multiprocessor Programming
114
On Older Architectures
• IBM 360
– testAndSet (getAndSet)
• NYU UltraComputer
– getAndAdd (fetchAndAdd)
• Neither universal
– Except for 2 threads
114Art of Multiprocessor Programming
115
On Newer Architectures
• Intel x86, Itanium, SPARC
– compareAndSet (CAS, CMPXCHG)
• Alpha AXP, PowerPC
– Load-locked/store-conditional
• All universal
– For any number of threads
• Trend is clear …
115Art of Multiprocessor Programming
Practical Implications
• Any architecture that does not provide a
universal primitive has inherent
limitations
• You cannot avoid locking for concurrent
data structures …
116Art of Multiprocessor Programming
117
Shared-Memory Computability
Wait-free/Lock-free computable
=
Threads with methods that solve n-consensus
10011Universal
Object
117Art of Multiprocessor Programming
Veni, Vidi, Vici
• We saw
– how to define concurrent objects
118118Art of Multiprocessor Programming
Veni, Vidi, Vici
• We saw
– how to define concurrent objects
• We discussed
– computational power of machine
instructions
119119Art of Multiprocessor Programming
Veni, Vidi, Vici
• We saw
– how to define concurrent objects
• We discussed
– computational power of machine
instructions
• Next
– use these foundations to understand the
real world
120120Art of Multiprocessor Programming
This work is licensed under a Creative Commons Attribution-
NonCommercial-ShareAlike 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.
121Art of Multiprocessor Programming