Art of Multiprocessor Programming

advertisement
Concurrent Objects
Companion slides for
The Art of Multiprocessor Programming
by Maurice Herlihy & Nir Shavit
Modified by Pavol Černý,
Programming Paradigms for Concurrency,
Fall 2010, IST Austria
Concurrent Computation
memory
object
object
Art of Multiprocessor
Programming
2
Objectivism
• What is a concurrent object?
– How do we describe one?
– How do we implement one?
– How do we tell if we’re right?
Art of Multiprocessor
Programming
3
Objectivism
• What is a concurrent object?
– How do we describe one?
– How do we tell if we’re right?
Art of Multiprocessor
Programming
4
FIFO Queue: Enqueue Method
q.enq( )
Art of Multiprocessor
Programming
5
FIFO Queue: Dequeue Method
q.deq()/
Art of Multiprocessor
Programming
6
A Lock-Based Queue
class LockBasedQueue<T> {
int head, tail;
T[] items;
Lock lock;
public LockBasedQueue(int capacity) {
head = 0; tail = 0;
lock = new ReentrantLock();
items = (T[]) new Object[capacity];
}
Art of Multiprocessor
Programming
7
A Lock-Based Queue
head
tail
0
1
y z 2
class LockBasedQueue<T> {
int head, tail;
T[] items;
Lock lock;
public LockBasedQueue(int capacity) {
head = 0; tail = 0;
lock = new ReentrantLock();
items = (T[]) new Object[capacity];
}
capacity-1
Queue fields
protected by
single shared lock
Art of Multiprocessor
Programming
8
A Lock-Based Queue
head
tail
0
1
y z 2
class LockBasedQueue<T> {
int head, tail;
T[] items;
Lock lock;
public LockBasedQueue(int capacity) {
head = 0; tail = 0;
lock = new ReentrantLock();
items = (T[]) new Object[capacity];
}
capacity-1
Initially head = tail
Art of Multiprocessor
Programming
9
Implementation: Deq
head
tail
0
public T deq() throws EmptyException
capacity-1 {
y z
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
lock.unlock();
}
}
Art of Multiprocessor
Programming
1
2
10
Implementation: Deq
head
tail
0
1
public T deq() throws EmptyException
capacity-1 {
y z 2
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
Method calls
lock.unlock();
mutually exclusive
}
}
Art of Multiprocessor
Programming
11
Implementation: Deq
head
tail
0
1
public T deq() throws EmptyException
capacity-1 {
y z 2
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
If queue empty
lock.unlock();
}
throw exception
}
Art of Multiprocessor
Programming
12
Implementation: Deq
head
tail
0
1
public T deq() throws EmptyException
capacity-1 {
y z 2
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
Queue not empty:
lock.unlock();
}
remove item and update
}
head
Art of Multiprocessor
Programming
13
Implementation: Deq
head
tail
0
1
public T deq() throws EmptyException
capacity-1 {
y z 2
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
Return result
lock.unlock();
}
}
Art of Multiprocessor
Programming
14
Implementation: Deq
head
tail
0
1
public T deq() throws EmptyException
capacity-1 {
y z 2
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
Release lock no
} finally {
matter what!
lock.unlock();
}
}
Art of Multiprocessor
Programming
15
Implementation: Deq
public T deq() throws EmptyException {
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
lock.unlock();
}
}
Art of Multiprocessor
Programming
16
Interface:
List-Based Set
Unordered collection of items, No duplicates
add(x) put x in set
remove(x) take x out of set
contains(x) tests if x in set
Implementation:
-∞
3
5
…
∞
Concurrent lists
Concurrent lists
“lock what you modify”
P1: remove(7)
prev
3
prev
Step 1
7
5
curr
P2:
remove(5)
curr
9
Concurrent lists
Concurrent lists
“lock what you modify”
P1: remove(7)
prev
3
7
5
prev
curr
P2:
remove(5)
curr
9
prev.next:=
curr.next
Concurrent lists
Concurrent lists
“lock what you modify”
3
Step 2
5
P2:
remove(5)
P1: remove(7)
7
9
Concurrent lists
Concurrent lists
“lock what you modify”
3
Step 3
5
P2:
remove(5)
P1: remove(7)
7
9
Concurrent lists
Concurrent lists
“lock what you modify”
3
Step 4
5
P2:
remove(5)
P1: remove(7)
7
9
Concurrent lists
Concurrent lists
“lock what you modify”
3
Step 5
5
P2:
remove(5)
P1: remove(7)
7
9
Concurrent lists
Concurrent lists
“lock what you modify”
3
5
P2:
remove(5)
P1: remove(7)
7
9
Lock-free list
Lock-free linked
list from
[Herlihy-Shavit]
public boolean remove(T item) {
whileexpRef,
(true) { bool b)
p.attemptMark(T
(pred,curr)
= find(head,
key);
If p==expRef, update
the
mark
if (curr.key != key) {// the key not present
return false;
} else {// the key present
Node succ = curr.next.getReference();
snip = curr.next.attemptMark(succ, true);
if (!snip) continue;
p.compareAndSet(T expRef,
T newRef,
pred.next.compareAndSet(curr, succ, false, false);
bool expMark, bool
newMark)
return true;
If p==expRef, p.mark==expMark,
}
update}the mark
}
Lock-free list remove
remove(7)
prev
3
5
curr
7
succ
M
9
snip = curr.next.attemptMark(succ, true);
…
snip = pred.next.compareAndSet(curr,succ, false, false);
Defining concurrent
implementations
• Need a way to specify a concurrent
queue (concurrent list) object
• Need a way to prove that an
algorithm implements the object’s
specification
• Lets talk about object specifications
…
Art of Multiprocessor
Programming
27
Correctness and Progress
• In a concurrent setting, we need to
specify both the safety and the liveness
properties of an object
• Need a way to define
– when an implementation is correct
– the conditions under which it guarantees
progress
Lets begin with correctness
Art of Multiprocessor
Programming
28
Sequential Objects
• Each object has a state
– Usually given by a set of fields
– Queue example: sequence of items
• Each object has a set of methods
– Only way to manipulate state
– Queue example: enq and deq methods
Art of Multiprocessor
Programming
29
Sequential Specifications
• If (precondition)
– the object is in such-and-such a state
– before you call the method,
• Then (postcondition)
– the method will return a particular value
– or throw a particular exception.
• and (postcondition, con’t)
– the object will be in some other state
– when the method returns,
Art of Multiprocessor
Programming
30
Pre and PostConditions for
Dequeue
• Precondition:
– Queue is non-empty
• Postcondition:
– Returns first item in queue
• Postcondition:
– Removes first item in queue
Art of Multiprocessor
Programming
31
Pre and PostConditions for
Dequeue
• Precondition:
– Queue is empty
• Postcondition:
– Throws Empty exception
• Postcondition:
– Queue state unchanged
Art of Multiprocessor
Programming
32
Why Sequential Specifications
Totally Rock
• Interactions among methods captured by
side-effects on object state
– State meaningful between method calls
• Documentation size linear in number of
methods
– Each method described in isolation
• Can add new methods
– Without changing descriptions of old methods
Art of Multiprocessor
Programming
33
What About Concurrent
Specifications ?
• Methods?
• Documentation?
• Adding new methods?
Art of Multiprocessor
Programming
34
Methods Take Time
time
Art of Multiprocessor
Programming
35
Methods Take Time
invocation
12:00
q.enq(...
)
time
Art of Multiprocessor
Programming
36
Methods Take Time
invocation
12:00
q.enq(...
)
Method call
time
Art of Multiprocessor
Programming
37
Methods Take Time
invocation
12:00
q.enq(...
)
Method call
time
Art of Multiprocessor
Programming
38
Methods Take Time
invocation
12:00
response
12:01
q.enq(...
)
void
Method call
time
Art of Multiprocessor
Programming
39
Sequential vs Concurrent
• Sequential
– Methods take time? Who knew?
• Concurrent
– Method call is not an event
– Method call is an interval.
Art of Multiprocessor
Programming
40
Concurrent Methods Take
Overlapping Time
time
Art of Multiprocessor
Programming
41
Concurrent Methods Take
Overlapping Time
Method call
time
Art of Multiprocessor
Programming
42
Concurrent Methods Take
Overlapping Time
Method call
Method call
time
Art of Multiprocessor
Programming
43
Concurrent Methods Take
Overlapping Time
Method call
Method call
Method call
time
Art of Multiprocessor
Programming
44
Sequential vs Concurrent
• Sequential:
– Object needs meaningful state only
between method calls
• Concurrent
– Because method calls overlap, object might
never be between method calls
Art of Multiprocessor
Programming
45
Sequential vs Concurrent
• Sequential:
– Each method described in isolation
• Concurrent
– Must characterize all possible interactions
with concurrent calls
• What if two enqs overlap?
• Two deqs? enq and deq? …
Art of Multiprocessor
Programming
46
Sequential vs Concurrent
• Sequential:
– Can add new methods without affecting
older methods
• Concurrent:
– Everything can potentially interact with
everything else
Art of Multiprocessor
Programming
47
Sequential vs Concurrent
• Sequential:
– Can add new methods without affecting
older methods
• Concurrent:
– Everything can potentially interact with
everything else
Art of Multiprocessor
Programming
48
The Big Question
• What does it mean for a concurrent
object to be correct?
– What is a concurrent FIFO queue?
– FIFO means strict temporal order
– Concurrent means ambiguous temporal
order
Art of Multiprocessor
Programming
49
Intuitively…
public T deq() throws EmptyException {
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
lock.unlock();
}
}
Art of Multiprocessor
Programming
50
Intuitively…
public T deq() throws EmptyException {
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
All modifications
lock.unlock();
of queue are done
}
mutually exclusive
}
Art of Multiprocessor
Programming
51
Intuitively
Lets capture the idea of describing
the concurrent via the sequential
lock()
q.deq
q.enq
lock()
enq
time
enq
unlock()
deq
unlock()
deq
Art of Multiprocessor
Programming
Behavior is
“Sequential”
52
Linearizability
• Each method should
– “take effect”
– Instantaneously
– Between invocation and response events
• Object is correct if this “sequential”
behavior is correct
• Any such concurrent object is
– Linearizable™
Art of Multiprocessor
Programming
53
Is it really about the object?
• Each method should
– “take effect”
– Instantaneously
– Between invocation and response events
• Sounds like a property of an
execution…
• A linearizable object: one all of whose
possible executions are linearizable
Art of Multiprocessor
Programming
54
Example
time
(6)
Art of Multiprocessor
Programming
55
Example
q.enq(x)
time
(6)
Art of Multiprocessor
Programming
56
Example
q.enq(x)
q.enq(y)
time
(6)
Art of Multiprocessor
Programming
57
Example
q.enq(x)
q.enq(y)
q.deq(x)
time
(6)
Art of Multiprocessor
Programming
58
Example
q.enq(x)
q.enq(y)
q.deq(y)
q.deq(x)
time
(6)
Art of Multiprocessor
Programming
59
Example
q.enq(x)
q.enq(y)
q.deq(y)
q.deq(x)
time
(6)
Art of Multiprocessor
Programming
60
Example
q.enq(x)
q.enq(y)
q.deq(y)
q.deq(x)
time
(6)
Art of Multiprocessor
Programming
61
Example
time
(5)
Art of Multiprocessor
Programming
62
Example
q.enq(x)
time
(5)
Art of Multiprocessor
Programming
63
Example
q.enq(x)
q.deq(y)
time
(5)
Art of Multiprocessor
Programming
64
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
65
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
66
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
67
Example
time
(4)
Art of Multiprocessor
Programming
68
Example
q.enq(x)
time
(4)
Art of Multiprocessor
Programming
69
Example
q.enq(x)
q.deq(x)
time
(4)
Art of Multiprocessor
Programming
70
Example
q.enq(x)
q.deq(x)
time
(4)
Art of Multiprocessor
Programming
71
Example
q.enq(x)
q.deq(x)
time
(4)
Art of Multiprocessor
Programming
72
Example
q.enq(x)
time
(8)
Art of Multiprocessor
Programming
73
Example
q.enq(x)
q.enq(y)
time
(8)
Art of Multiprocessor
Programming
74
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(8)
Art of Multiprocessor
Programming
75
Example
q.enq(x)
q.deq(y)
q.enq(y)
q.deq(x)
time
(8)
Art of Multiprocessor
Programming
76
Example
q.enq(x)
q.deq(y)
q.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
77
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(0)
time
(4)
Art of Multiprocessor
Programming
78
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(0)
write(1) already
happened time
(4)
Art of Multiprocessor
Programming
79
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(0)
write(1) already
happened time
(4)
Art of Multiprocessor
Programming
80
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(0)
write(1) already
happened time
(4)
Art of Multiprocessor
Programming
81
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(1)
write(1) already
happened time
(4)
Art of Multiprocessor
Programming
82
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(1)
write(1) already
happened time
(4)
Art of Multiprocessor
Programming
83
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(1)
write(1) already
happened time
(4)
Art of Multiprocessor
Programming
84
Read/Write Register Example
write(0)
write(2)
write(1)
read(1)
time
(4)
Art of Multiprocessor
Programming
85
Read/Write Register Example
write(0)
write(2)
write(1)
read(1)
time
(4)
Art of Multiprocessor
Programming
86
Read/Write Register Example
write(0)
write(2)
write(1)
read(1)
time
(4)
Art of Multiprocessor
Programming
87
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(1)
time
(2)
Art of Multiprocessor
Programming
88
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(1)
time
(2)
Art of Multiprocessor
Programming
89
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(1)
time
(2)
Art of Multiprocessor
Programming
90
Read/Write Register Example
write(0)
read(1)
write(2)
write(1)
read(2)
time
(2)
Art of Multiprocessor
Programming
91
Talking About Executions
• Why?
– Can’t we specify the linearization point of
each operation without describing an
execution?
• Not Always
– In some cases, linearization point depends
on the execution
Art of Multiprocessor
Programming
92
Formal Model of Executions
• Define precisely what we mean
– Ambiguity is bad when intuition is weak
• Allow reasoning
Art of Multiprocessor
Programming
93
Split Method Calls into Two
Events
• Invocation
– method name & args
– q.enq(x)
• Response
– result or exception
– q.enq(x) returns void
– q.deq() returns x
– q.deq() throws empty
Art of Multiprocessor
Programming
94
Invocation Notation
A q.enq(x)
(4)
Art of Multiprocessor
Programming
95
Invocation Notation
A q.enq(x)
thread
(4)
Art of Multiprocessor
Programming
96
Invocation Notation
A q.enq(x)
thread
(4)
method
Art of Multiprocessor
Programming
97
Invocation Notation
A q.enq(x)
thread
method
object
(4)
Art of Multiprocessor
Programming
98
Invocation Notation
A q.enq(x)
thread
method
object
(4)
Art of Multiprocessor
Programming
arguments
99
Response Notation
A q: void
(2)
Art of Multiprocessor
Programming
100
Response Notation
A q: void
thread
(2)
Art of Multiprocessor
Programming
101
Response Notation
A q: void
thread
(2)
result
Art of Multiprocessor
Programming
102
Response Notation
A q: void
thread
result
object
(2)
Art of Multiprocessor
Programming
103
Response Notation
A q: void
thread
result
object
(2)
Art of Multiprocessor
Programming
104
Response Notation
A q: empty()
thread
exception
object
(2)
Art of Multiprocessor
Programming
105
History - Describing an Execution
A
A
A
H = B
B
B
B
q.enq(3)
q:void
q.enq(5)
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
Sequence of
invocations and
responses
106
Definition
• Invocation & response match if
Object names
agree
Thread
names agree
A q.enq(3)
A q:void
(1)
Art of Multiprocessor
Programming
Method call
107
Object Projections
H=
A
A
B
B
B
B
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
108
Object Projections
H|q =
A
A
B
B
B
B
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
109
Thread Projections
H=
A
A
B
B
B
B
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
110
Thread Projections
H|B =
A
A
B
B
B
B
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
111
Complete Subhistory
A
A
A
H = B
B
B
B
q.enq(3)
q:void
q.enq(5)
p.enq(4)
p:void
q.deq()
An invocation is
q:3
pending if it has no
matching respnse
Art of Multiprocessor
Programming
112
Complete Subhistory
A
A
A
H = B
B
B
B
q.enq(3)
q:void
q.enq(5)
p.enq(4)
p:void
q.deq()
May or may not
q:3
have taken effect
Art of Multiprocessor
Programming
113
Complete Subhistory
A
A
A
H = B
B
B
B
q.enq(3)
q:void
q.enq(5)
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
discard pending
invocations
114
Complete Subhistory
A q.enq(3)
A q:void
Complete(H) = B
B
B
B
p.enq(4)
p:void
q.deq()
q:3
Art of Multiprocessor
Programming
115
Sequential Histories
A
A
B
B
B
B
A
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
q:enq(5)
(4)
Art of Multiprocessor
Programming
116
Sequential Histories
A
A
B
B
B
B
A
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
q:enq(5)
(4)
match
Art of Multiprocessor
Programming
117
Sequential Histories
A
A
B
B
B
B
A
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
q:enq(5)
(4)
match
match
Art of Multiprocessor
Programming
118
Sequential Histories
A
A
B
B
B
B
A
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
q:enq(5)
(4)
match
match
match
Art of Multiprocessor
Programming
119
Sequential Histories
A
A
B
B
B
B
A
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
q:enq(5)
(4)
match
match
match
Final pending
invocation OK
Art of Multiprocessor
Programming
120
Sequential Histories
A
A
B
B
B
B
A
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
q:enq(5)
(4)
match
match
match
Final pending
invocation OK
Art of Multiprocessor
Programming
121
Well-Formed Histories
A
B
B
H= B
A
B
q.enq(3)
p.enq(4)
p:void
q.deq()
q:void
q:3
Art of Multiprocessor
Programming
122
Well-Formed Histories
Per-thread
projections sequential
A
B
B
H= B
A
B
q.enq(3)
p.enq(4)
p:void
q.deq()
q:void
q:3
B
H|B= B
B
B
Art of Multiprocessor
Programming
p.enq(4)
p:void
q.deq()
q:3
123
Well-Formed Histories
Per-thread
projections sequential
A
B
B
H= B
A
B
q.enq(3)
p.enq(4)
p:void
q.deq()
q:void
q:3
B
H|B= B
B
B
p.enq(4)
p:void
q.deq()
q:3
A q.enq(3)
H|A=
A q:void
Art of Multiprocessor
Programming
124
Equivalent Histories
Threads see the same
thing in both
A
B
B
H= B
A
B
q.enq(3)
p.enq(4)
p:void
q.deq()
q:void
q:3
H|A = G|A
H|B = G|B
A
A
B
G= B
B
B
Art of Multiprocessor
Programming
q.enq(3)
q:void
p.enq(4)
p:void
q.deq()
q:3
125
Sequential Specifications
• A sequential specification is some way
of telling whether a
– Single-thread, single-object history
– Is legal
• For example:
– Pre and post-conditions
– But plenty of other techniques exist …
Art of Multiprocessor
Programming
126
Legal Histories
• A sequential (multi-object) history H is
legal if
– For every object x
– H|x is in the sequential spec for x
Art of Multiprocessor
Programming
127
Precedence
A
B
B
A
B
B
q.enq(3)
p.enq(4)
p.void
q:void
q.deq()
q:3
A method call precedes
another if response
event precedes
invocation event
Method call
(1)
Art of Multiprocessor
Programming
Method call
128
Non-Precedence
A
B
B
B
A
B
q.enq(3)
p.enq(4)
p.void
q.deq()
q:void
q:3
Some method calls
overlap one another
Method call
Method call
(1)
Art of Multiprocessor
Programming
129
Notation
• Given
– History H
– method executions m0 and m1 in H
• We say m0 H m1, if
– m0 precedes m1
• Relation m0 H m1 is a
m0
m1
– Partial order
– Total order if H is sequential
Art of Multiprocessor
Programming
130
Linearizability
• History H is linearizable if it can be
extended to G by
– Appending zero or more responses to
pending invocations
– Discarding other pending invocations
• So that G is equivalent to
– Legal sequential history S
– where G  S
Art of Multiprocessor
Programming
131
What is G  S
G = {ac,bc}
S = {ab,ac,bc}
a
b
G
time
(8)
Art of Multiprocessor
Programming
c
S
132
Remarks
• Some pending invocations
– Took effect, so keep them
– Discard the rest
• Condition G  S
– Means that S respects “real-time order” of
G
Art of Multiprocessor
Programming
133
Example
A
B
B
B
B
B
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
q:enq(6)
A. q.enq(3)
B.q.enq(4)
B.q.deq(4)
B. q.enq(6)
time
Art of Multiprocessor
Programming
134
Example
A
B
B
B
B
B
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
q:enq(6)
Complete this
pending
invocation
A. q.enq(3)
B.q.enq(4)
B.q.deq(3)
B. q.enq(6)
time
Art of Multiprocessor
Programming
135
Example
A
B
B
B
B
B
A
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
q:enq(6)
q:void
Complete this
pending
invocation
A.q.enq(3)
B.q.enq(4)
B.q.deq(4)
B. q.enq(6)
time
Art of Multiprocessor
Programming
136
Example
discard this one
A
B
B
B
B
B
A
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
q:enq(6)
q:void
A.q.enq(3)
B.q.enq(4)
B.q.deq(4)
B. q.enq(6)
time
Art of Multiprocessor
Programming
137
Example
discard this one
A
B
B
B
B
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
A q:void
A.q.enq(3)
B.q.enq(4)
B.q.deq(4)
time
Art of Multiprocessor
Programming
138
Example
A
B
B
B
B
A
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
q:void
A.q.enq(3)
B.q.enq(4)
B.q.deq(4)
time
Art of Multiprocessor
Programming
139
Example
A
B
B
B
B
A
q.enq(3)
q.enq(4)
q:void
q.deq()
q:3
q:void
A
A
B
B
B
B
q.enq(3)
q:void
q.enq(4)
q:void
q.deq()
q:3
A.q.enq(3)
B.q.enq(4)
B.q.deq(4)
time
Art of Multiprocessor
Programming
140
Example
Equivalent sequential history
A
B
B
B
B
A
q.enq(3)
q.enq(4)
q:void
q.deq()
q:4
q:void
A
A
B
B
B
B
q.enq(3)
q:void
q.enq(4)
q:void
q.deq()
q:3
A.q.enq(3)
B.q.enq(4)
B.q.deq(4)
time
Art of Multiprocessor
Programming
141
Unlinearizable execution
Concurrent lists
“lock what you modify”
3
Step 6
5
P2:
remove(5)
P1: remove(7)
7
9
Reasoning About
Lineraizability: Locking
head
tail
0
public T deq() throws EmptyException
capacity-1 {
y z
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
lock.unlock();
}
}
Art of Multiprocessor
Programming
1
2
143
Reasoning About
Lineraizability: Locking
public T deq() throws EmptyException {
lock.lock();
try {
if (tail == head)
throw new EmptyException();
T x = items[head % items.length];
head++;
return x;
} finally {
Linearization points
lock.unlock();
are when locks are
}
}
released
Art of Multiprocessor
Programming
144
Strategy
• Identify one atomic step where method
“happens”
– Critical section
– Machine instruction
• Doesn’t always work
– Might need to define several different
steps for a given method
Art of Multiprocessor
Programming
145
Linearizability: Summary
• Powerful specification tool for shared
objects
• Allows us to capture the notion of
objects being “atomic”
• There is a lot of ongoing research in
verification community to build tools
that can verify/debug concurrent
implementations wrt linearizability
Art of Multiprocessor
Programming
146
Alternative: Sequential
Consistency
• History H is Sequentially Consistent
if it can be extended to G by
– Appending zero or more responses to
pending invocations
– Discarding other pending invocations
• So that G is equivalent to a
– Legal sequential history S
Differs from
linearizability
– Where G  S
Art of Multiprocessor
Programming
147
Alternative: Sequential
Consistency
• No need to preserve real-time order
– Cannot re-order operations done by the
same thread
– Can re-order non-overlapping operations
done by different threads
• Often used to describe
multiprocessor memory architectures
Art of Multiprocessor
Programming
148
Example
time
(5)
Art of Multiprocessor
Programming
149
Example
q.enq(x)
time
(5)
Art of Multiprocessor
Programming
150
Example
q.enq(x)
q.deq(y)
time
(5)
Art of Multiprocessor
Programming
151
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
152
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
153
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
154
Example
q.enq(x)
q.deq(y)
q.enq(y)
time
(5)
Art of Multiprocessor
Programming
155
Theorem
Sequential Consistency is not a
local property
(and thus we lose composability…)
Art of Multiprocessor
Programming
156
FIFO Queue Example
p.enq(x)
q.enq(x)
p.deq(y)
time
Art of Multiprocessor
Programming
157
FIFO Queue Example
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
158
FIFO Queue Example
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
History H
time
Art of Multiprocessor
Programming
159
H|p Sequentially Consistent
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
160
H|q Sequentially Consistent
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
161
Ordering imposed by p
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
162
Ordering imposed by q
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
163
Ordering imposed by both
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
164
Combining orders
p.enq(x)
q.enq(x)
q.enq(y)
p.deq(y)
p.enq(y)
q.deq(x)
time
Art of Multiprocessor
Programming
165
Composability Theorem
• History H is linearizable if and only if
– For every object x
– H|x is linearizable
Art of Multiprocessor
Programming
166
Why Does Composability Matter?
• Modularity
• Can prove linearizability of objects in
isolation
• Can compose independently-implemented
objects
Art of Multiprocessor
Programming
167
Critical Sections
• Easy way to implement linearizability
– Take sequential object
– Make each method a critical section
• Problems
– Blocking
– No concurrency
Art of Multiprocessor
Programming
168
Linearizability
• Linearizability
– Operation takes effect instantaneously
between invocation and response
– Uses sequential specification, locality
implies composablity
– Good for high level objects
Art of Multiprocessor
Programming
169
Correctness: Linearizability
• Sequential Consistency
– Not composable
– Harder to work with
– Good way to think about hardware models
• We will use linearizability as in the
remainder of this course unless stated
otherwise
Art of Multiprocessor
Programming
170
Progress
• We saw an implementation whose
methods were lock-based (deadlockfree)
• We saw an implementation whose
methods did not use locks
• How do they relate?
Art of Multiprocessor
Programming
171
Progress Conditions
• Deadlock-free: some thread trying to acquire
the lock eventually succeeds.
• Starvation-free: every thread trying to
acquire the lock eventually succeeds.
• Lock-free: some thread calling a method
eventually returns.
• Wait-free: every thread calling a method
eventually returns.
Art of Multiprocessor
Programming
172
Progress Conditions
Blocking
Non-Blocking
Everyone
makes
progress
Wait-free
Starvation-free
Someone
makes
progress
Lock-free
Deadlock-free
Art of Multiprocessor
Programming
173
Summary
• We will look at linearizable blocking and
non-blocking implementations of
objects.
Art of Multiprocessor
Programming
174
Download