Concurrent Objects: Companion Slides For by Maurice Herlihy & Nir Shavit

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 184

Concurrent Objects

Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Concurrent Computation

memory

object
Art of Multiprocessor Programming

object
2

Objectivism
What is a concurrent object?
How do we describe one? How do we implement one? How do we tell if were right?

Art of Multiprocessor Programming

Objectivism
What is a concurrent object?
How do we describe one?
How do we tell if were right?

Art of Multiprocessor Programming

FIFO Queue: Enqueue Method

q.enq( )

Art of Multiprocessor Programming

FIFO Queue: Dequeue Method

q.deq()/

Art of Multiprocessor Programming

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

A Lock-Based Queue
head
0 capacity-1

tail
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]; }

Queue fields protected by single shared lock


Art of Multiprocessor Programming 8

A Lock-Based Queue
head
0 capacity-1

tail
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]; }

Initially head = tail

Art of Multiprocessor Programming

Implementation: Deq
head tail
0 1 2

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

10

Implementation: Deq
head
0 1

tail

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
0 1

tail

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
0 1

tail

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
0 1

tail

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

Now consider the following implementation


The same thing without mutual exclusion For simplicity, only two threads
One thread enq only The other deq only

Art of Multiprocessor Programming

17

Wait-free 2-Thread Queue


public class WaitFreeQueue { int head = 0, tail = 0; items = (T[]) new Object[capacity];
head
0 capacity-1

tail

y z

1 2

public void enq(Item x) { if (tail-head == capacity) throw new FullException(); items[tail % capacity] = x; tail++; } public Item deq() { if (tail == head) throw new EmptyException(); Item item = items[head % capacity]; head++; return item; }} Art of Multiprocessor 18
Programming

Wait-free 2-Thread Queue


public class WaitFreeQueue { int head = 0, tail = 0; items = (T[]) new Object[capacity];
head head
capacity-1 capacity-1 0 0

tail tail
1

yy zz

1
2 2

public void enq(Item x) { if (tail-head == capacity) throw new FullException(); items[tail % capacity] = x; tail++; } public Item deq() { if (tail == head) throw new EmptyException(); Item item = items[head % capacity]; head++; return item; }} Art of Multiprocessor 19
Programming

Wait-free 2-Thread Queue


public class WaitFreeQueue {
head
0 1 2 capacity-1

tail

y z int head = 0, tail = 0; items = (T[]) new Object[capacity];

public void enq(Item x) { if (tail-head == capacity) throw new FullException(); items[tail % capacity] = x; tail++; } public Item deq() { if (tail == head) throw new EmptyException(); Queue is updated without lock! Item item = items[head %a capacity]; head++; return item; }} Art of Multiprocessor 20
Programming

Defining concurrent queue implementations


Need a way to specify a concurrent queue object Need a way to prove that an algorithm implements the objects specification Lets talk about object specifications
Art of Multiprocessor Programming 21

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 22

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

23

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, cont) the object will be in some other state when the method returns,
Art of Multiprocessor Programming 24

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

25

Pre and PostConditions for Dequeue


Precondition:
Queue is empty

Postcondition:
Throws Empty exception

Postcondition:
Queue state unchanged

Art of Multiprocessor Programming

26

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

27

What About Concurrent Specifications ?


Methods? Documentation? Adding new methods?

Art of Multiprocessor Programming

28

Methods Take Time

time
Art of Multiprocessor Programming 29

Methods Take Time


invocation 12:00
q.enq(...)

time
Art of Multiprocessor Programming 30

Methods Take Time


invocation 12:00
q.enq(...)

Method call time


Art of Multiprocessor Programming 31

Methods Take Time


invocation 12:00
q.enq(...)

Method call time


Art of Multiprocessor Programming 32

Methods Take Time


invocation 12:00
q.enq(...)

response 12:01
void Method call time
Art of Multiprocessor Programming 33

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

34

Concurrent Methods Take Overlapping Time

time
Art of Multiprocessor Programming 35

Concurrent Methods Take Overlapping Time

Method call

time
Art of Multiprocessor Programming 36

Concurrent Methods Take Overlapping Time

Method call Method call time


Art of Multiprocessor Programming 37

Concurrent Methods Take Overlapping Time

Method call Method call time

Method call

Art of Multiprocessor Programming

38

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

39

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

40

Sequential vs Concurrent
Sequential:
Can add new methods without affecting older methods

Concurrent:
Everything can potentially interact with everything else

Art of Multiprocessor Programming

41

Sequential vs Concurrent
Sequential:
Can add new methods without affecting older methods

Concurrent:
Everything can potentially interact with everything else

Art of Multiprocessor Programming

42

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

43

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

44

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

45

Lets capture the idea of describing the concurrent via the sequential
lock()

Intuitively
q.deq deq

unlock()

q.enq
lock()

enq

unlock()

Behavior is Sequential

Art of Multiprocessor Programming

time enq

deq

46

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

47

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 48

Example

time
(6)

Art of Multiprocessor Programming

49

Example

q.enq(x)

time
(6)

Art of Multiprocessor Programming

50

Example

q.enq(x) q.enq(y) time


(6)

Art of Multiprocessor Programming

51

Example

q.enq(x) q.enq(y) q.deq(x) time


(6)

Art of Multiprocessor Programming

52

Example

q.enq(x) q.enq(y) q.deq(x) time


(6)

q.deq(y)

Art of Multiprocessor Programming

53

Example

q.enq(x) q.enq(y) q.deq(x) time


(6)

q.deq(y)

Art of Multiprocessor Programming

54

Example

q.enq(x) q.enq(y) q.deq(x) time


(6)

q.deq(y)

Art of Multiprocessor Programming

55

Example

time
(5)

Art of Multiprocessor Programming

56

Example

q.enq(x)

time
(5)

Art of Multiprocessor Programming

57

Example

q.enq(x)

q.deq(y)

time
(5)

Art of Multiprocessor Programming

58

Example

q.enq(x)

q.deq(y) q.enq(y) time

(5)

Art of Multiprocessor Programming

59

Example

q.enq(x)

q.deq(y)

q.enq(y)
time
(5)

Art of Multiprocessor Programming

60

Example

q.enq(x)

q.deq(y)

q.enq(y)
time
(5)

Art of Multiprocessor Programming

61

Example

time
(4)

Art of Multiprocessor Programming

62

Example

q.enq(x)

time
(4)

Art of Multiprocessor Programming

63

Example

q.enq(x)
q.deq(x) time
(4)

Art of Multiprocessor Programming

64

Example

q.enq(x)

q.deq(x)
time
(4)

Art of Multiprocessor Programming

65

Example

q.enq(x)

q.deq(x)
time
(4)

Art of Multiprocessor Programming

66

Example

q.enq(x)

time
(8)

Art of Multiprocessor Programming

67

Example

q.enq(x) q.enq(y) time


(8)

Art of Multiprocessor Programming

68

Example

q.enq(x) q.enq(y)

q.deq(y)

time
(8)

Art of Multiprocessor Programming

69

Example

q.enq(x) q.enq(y)

q.deq(y) q.deq(x) time

(8)

Art of Multiprocessor Programming

70

Comme ci Example Comme a

q.enq(x)

q.deq(y)

q.enq(y)
time

q.deq(x)

Art of Multiprocessor Programming

71

Read/Write Register Example

write(0)

read(1) write(1) time

write(2) read(0)

(4)

Art of Multiprocessor Programming

72

Read/Write Register Example

write(0)

read(1) write(1)

write(2) read(0)

write(1) already happened time


(4)

Art of Multiprocessor Programming

73

Read/Write Register Example

write(0)

read(1) write(1)

write(2) read(0)

write(1) already happened time


(4)

Art of Multiprocessor Programming

74

Read/Write Register Example

write(0)

read(1) write(1)

write(2) read(0)

write(1) already happened time


(4)

Art of Multiprocessor Programming

75

Read/Write Register Example

write(0)

read(1) write(1)

write(2) read(1)

write(1) already happened time


(4)

Art of Multiprocessor Programming

76

Read/Write Register Example

write(0)

read(1) write(1)

write(2) read(1)

write(1) already happened time


(4)

Art of Multiprocessor Programming

77

Read/Write Register Example

write(0)

read(1) write(1)

write(2) read(1)

write(1) already happened time


(4)

Art of Multiprocessor Programming

78

Read/Write Register Example

write(0) write(1) time


(4)

write(2) read(1)

Art of Multiprocessor Programming

79

Read/Write Register Example

write(0) write(1) time


(4)

write(2) read(1)

Art of Multiprocessor Programming

80

Read/Write Register Example

write(0) write(1) time


(4)

write(2) read(1)

Art of Multiprocessor Programming

81

Read/Write Register Example

write(0)

read(1) write(1) time

write(2) read(1)

(2)

Art of Multiprocessor Programming

82

Read/Write Register Example

write(0)

read(1) write(1) time

write(2) read(1)

(2)

Art of Multiprocessor Programming

83

Read/Write Register Example

write(0)

read(1) write(1) time

write(2) read(1)

(2)

Art of Multiprocessor Programming

84

Read/Write Register Example

write(0)

read(1) write(1) time

write(2) read(2)

(2)

Art of Multiprocessor Programming

85

Talking About Executions


Why?
Cant 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

86

Formal Model of Executions


Define precisely what we mean
Ambiguity is bad when intuition is weak

Allow reasoning
Formal But mostly informal
In the long run, actually more important Ask me why!

Art of Multiprocessor Programming

87

Split Method Calls into Two Events


Invocation Response
method name & args q.enq(x) result or exception q.enq(x) returns void q.deq() returns x q.deq() throws empty
Art of Multiprocessor Programming 88

Invocation Notation
A q.enq(x)

(4)

Art of Multiprocessor Programming

89

Invocation Notation
A q.enq(x) thread

(4)

Art of Multiprocessor Programming

90

Invocation Notation
A q.enq(x) thread method

(4)

Art of Multiprocessor Programming

91

Invocation Notation
A q.enq(x) thread object
(4)

method

Art of Multiprocessor Programming

92

Invocation Notation
A q.enq(x) thread object
(4)

method arguments
93

Art of Multiprocessor Programming

Response Notation
A q: void

(2)

Art of Multiprocessor Programming

94

Response Notation
A q: void thread

(2)

Art of Multiprocessor Programming

95

Response Notation
A q: void thread result

(2)

Art of Multiprocessor Programming

96

Response Notation
A q: void thread object
(2)

result

Art of Multiprocessor Programming

97

Response Notation
A q: void thread object
(2)

result

Art of Multiprocessor Programming

98

Response Notation
A q: empty() thread object
(2)

exception

Art of Multiprocessor Programming

99

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


100

Definition
Invocation & response match if Thread names agree A q:void
(1)

Object names agree


Method call

A q.enq(3)

Art of Multiprocessor Programming

101

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 102

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 103

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 104

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 105

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
106 Art of Multiprocessor Programming

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 107

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


108

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 109

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

110

Sequential Histories
match

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

111

Sequential Histories
match

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

112

Sequential Histories
match

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

113

Sequential Histories
match

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 Final pending invocation OK
Art of Multiprocessor Programming 114

Sequential Histories
match

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 Final pending invocation OK
Art of Multiprocessor Programming 115

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

116

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

Art of Multiprocessor Programming

117

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 118

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


q.enq(3) q:void p.enq(4) p:void q.deq() q:3
119

A A B G= B B B
Art of Multiprocessor Programming

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

120

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

121

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 Method call
122

(1)

Art of Multiprocessor Programming

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

123

Notation
Given
History H method executions m0 and m1 in H m0 precedes m1
m0 m1

We say m0 H m1, if

Relation m0 H m1 is a

Partial order Total order if H is sequential


Art of Multiprocessor Programming 124

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 Legal sequential history S where G S
Art of Multiprocessor Programming

So that G is equivalent to

125

What is G S
G = {ac,bc} S = {ab,ac,bc}
a b G time
(8)

S
126

Art of Multiprocessor Programming

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

127

Example
A B B B B B q.enq(3) q.enq(4) q:void q.deq() q:4 q:enq(6)

A. q.enq(3) B.q.enq(4) B.q.deq(4) time


Art of Multiprocessor Programming 128

B. q.enq(6)

Example
A B B B B B q.enq(3) q.enq(4) q:void q.deq() q:4 q:enq(6) Complete this pending invocation

A. q.enq(3) B.q.enq(4) B.q.deq(3) time


Art of Multiprocessor Programming 129

B. q.enq(6)

Example
A B B B B B A q.enq(3) q.enq(4) q:void q.deq() q:4 q:enq(6) q:void
A.q.enq(3) B.q.enq(4) B.q.deq(4) time
Art of Multiprocessor Programming 130

Complete this pending invocation

B. q.enq(6)

Example
A B B B B B A q.enq(3) q.enq(4) q:void q.deq() q:4 q:enq(6) q:void
A.q.enq(3) B.q.enq(4) B.q.deq(4) time
Art of Multiprocessor Programming 131

discard this one

B. q.enq(6)

Example
A B B B B q.enq(3) q.enq(4) q:void q.deq() q:4

discard this one

A q:void
A.q.enq(3) B.q.enq(4) B.q.deq(4) time
Art of Multiprocessor Programming 132

Example
A B B B B A q.enq(3) q.enq(4) q:void q.deq() q:4 q:void
A.q.enq(3)
B.q.enq(4) B.q.deq(4)

Art of Multiprocessor Programming

time

133

Example
A B B B B A q.enq(3) q.enq(4) q:void q.deq() q:4 q:void B B A A B B
A.q.enq(3)
B.q.enq(4) B.q.deq(4)

q.enq(4) q:void q.enq(3) q:void q.deq() q:4

Art of Multiprocessor Programming

time

134

Example
Equivalent sequential history A B B B B A q.enq(3) q.enq(4) q:void q.deq() q:4 q:void B B A A B B
A.q.enq(3)
B.q.enq(4) B.q.deq(4)

q.enq(4) q:void q.enq(3) q:void q.deq() q:4

Art of Multiprocessor Programming

time

135

Composability Theorem
History H is linearizable if and only if
For every object x H|x is linearizable

We care about objects only!


(Materialism?)

Art of Multiprocessor Programming

141

Why Does Composability Matter?


Modularity Can prove linearizability of objects in isolation Can compose independently-implemented objects

Art of Multiprocessor Programming

142

Reasoning About Linearizability: Locking


public T deq() throws EmptyException { 1 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(); } }
0

head

tail
2

Art of Multiprocessor Programming

143

Reasoning About Linearizability: 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

More Reasoning: Wait-free


public class WaitFreeQueue { int head = 0, tail = 0; items = (T[]) new Object[capacity];
head head
capacity-1 capacity-1 0 0

tail tail
1

yy zz

1
2 2

public void enq(Item x) { if (tail-head == capacity) throw new FullException(); items[tail % capacity] = x; tail++; } public Item deq() { if (tail == head) throw new EmptyException(); Item item = items[head % capacity]; head++; return item; }} Art of Multiprocessor 145
Programming

More Reasoning: Wait-free


public class WaitFreeQueue { int head = 0, items = (T[])

public void enq(Item x) { if (tail-head == capacity) throw new FullException(); items[tail % capacity] = x; tail++; } public Item deq() { if (tail == head) throw new EmptyException(); Item item = items[head % capacity]; head++; return item; }} Art of Multiprocessor 146
Programming

Linearization order is y z tail = 0; order head and tail new Object[capacity]; fields modified
0 1 capacity-1 2

head

tail

Strategy
Identify one atomic step where method happens
Critical section Machine instruction

Doesnt always work


Might need to define several different steps for a given method

Art of Multiprocessor Programming

147

Linearizability: Summary
Powerful specification tool for shared objects Allows us to capture the notion of objects being atomic Dont leave home without it

Art of Multiprocessor Programming

148

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 Legal sequential history S

So that G is equivalent to a
Where G S
Art of Multiprocessor Programming

Differs from linearizability

149

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 150

Example

time
(5)

Art of Multiprocessor Programming

151

Example

q.enq(x)

time
(5)

Art of Multiprocessor Programming

152

Example

q.enq(x)

q.deq(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

Example

q.enq(x)

q.deq(y)

q.enq(y)
time
(5)

Art of Multiprocessor Programming

156

Example

q.enq(x)

q.deq(y)

q.enq(y)
time
(5)

Art of Multiprocessor Programming

157

Theorem
Sequential Consistency is not a local property
(and thus we lose composability)

Art of Multiprocessor Programming

158

FIFO Queue Example


p.enq(x) q.enq(x) p.deq(y)

time
Art of Multiprocessor Programming 159

FIFO Queue Example


p.enq(x) q.enq(x) p.deq(y)

q.enq(y)

p.enq(y)

q.deq(x)

time
Art of Multiprocessor Programming 160

FIFO Queue Example


p.enq(x) q.enq(x) p.deq(y)

q.enq(y)

p.enq(y)

q.deq(x)

History H
time
Art of Multiprocessor Programming 161

H|p Sequentially Consistent


p.enq(x) q.enq(x) p.deq(y)

q.enq(y)

p.enq(y)

q.deq(x)

time
Art of Multiprocessor Programming 162

H|q Sequentially Consistent


p.enq(x) q.enq(x) p.deq(y)

q.enq(y)

p.enq(y)

q.deq(x)

time
Art of Multiprocessor Programming 163

Ordering imposed by p

p.enq(x)

q.enq(x)

p.deq(y) q.deq(x)

q.enq(y)

p.enq(y)

time
Art of Multiprocessor Programming 164

Ordering imposed by q

p.enq(x)

q.enq(x)

p.deq(y) q.deq(x)

q.enq(y)

p.enq(y)

time
Art of Multiprocessor Programming 165

Ordering imposed by both

p.enq(x)

q.enq(x)

p.deq(y) q.deq(x)

q.enq(y)

p.enq(y)

time
Art of Multiprocessor Programming 166

Combining orders

p.enq(x)

q.enq(x)

p.deq(y) q.deq(x)

q.enq(y)

p.enq(y)

time
Art of Multiprocessor Programming 167

Fact
Most hardware architectures dont support sequential consistency Because they think its too strong Heres another story

Art of Multiprocessor Programming

168

The Flag Example


x.write(1) y.read(0) x.read(0)

y.write(1)

time
Art of Multiprocessor Programming 169

The Flag Example


x.write(1) y.read(0) x.read(0)

y.write(1)

Each threads view is sequentially consistent


It went first
time
Art of Multiprocessor Programming 170

The Flag Example


x.write(1) y.read(0) x.read(0)

y.write(1)

Entire history isnt sequentially consistent


Cant both go first
Art of Multiprocessor Programming 171

time

The Flag Example


x.write(1) y.read(0) x.read(0)

y.write(1)

Is this behavior really so wrong?


We can argue either way
time
Art of Multiprocessor Programming 172

Opinion1: Its Wrong


This pattern Is exactly the flag principle
Beloved of Alice and Bob Heart of mutual exclusion
Peterson Bakery, etc.

Write mine, read yours

Its non-negotiable!
Art of Multiprocessor Programming 173

Opinion2: But It Feels So Right


Many hardware architects think that sequential consistency is too strong Too expensive to implement in modern hardware OK if flag principle
violated by default Honored by explicit request

Art of Multiprocessor Programming

174

Memory Hierarchy
On modern multiprocessors, processors do not read and write directly to memory. Memory accesses are very slow compared to processor speeds, Instead, each processor reads and writes directly to a cache
Art of Multiprocessor Programming 175

Memory Operations
To read a memory location,
load data into cache.

To write a memory location


update cached copy, lazily write cached data back to memory

Art of Multiprocessor Programming

176

While Writing to Memory


A processor can execute hundreds, or even thousands of instructions Why delay on every memory write? Instead, write back in parallel with rest of the program.

Art of Multiprocessor Programming

177

Revisionist History
Flag violation history is actually OK
processors delay writing to memory until after reads have been issued.

Otherwise unacceptable delay between read and write instructions. Who knew you wanted to synchronize?

Art of Multiprocessor Programming

178

Who knew you wanted to synchronize?


Writing to memory = mailing a letter Vast majority of reads & writes
Not for synchronization No need to idle waiting for post office

If you want to synchronize


Announce it explicitly Pay for it only when you need it

Art of Multiprocessor Programming

179

Explicit Synchronization
Memory barrier instruction
Flush unwritten caches Bring caches up to date

Compilers often do this for you


Entering and leaving critical sections

Expensive

Art of Multiprocessor Programming

180

Volatile
In Java, can ask compiler to keep a variable up-to-date with volatile keyword Also inhibits reordering, removing from loops, & other optimizations

Art of Multiprocessor Programming

181

Real-World Hardware Memory


Weaker than sequential consistency But you can get sequential consistency at a price OK for expert, tricky stuff
assembly language, device drivers, etc.

Linearizability more appropriate for high-level software


Art of Multiprocessor Programming 182

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

183

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

184

Progress
We saw an implementation whose methods were lock-based (deadlockfree) We saw an implementation whose methods did not use locks (lock-free) How do they relate?

Art of Multiprocessor Programming

185

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

186

Progress Conditions
Non-Blocking Everyone makes progress Someone makes progress Blocking

Wait-free Lock-free

Starvation-free Deadlock-free

Art of Multiprocessor Programming

187

Summary
We will look at linearizable blocking and non-blocking implementations of objects.

Art of Multiprocessor Programming

188

This work is licensed under a Creative Commons AttributionShareAlike 2.5 License.


You are free: to Share to copy, distribute and transmit the work to Remix to adapt the work Under the following conditions: Attribution. You must attribute the work to The Art of Multiprocessor Programming (but not in any way that suggests that the authors endorse you or your use of the work). Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to http://creativecommons.org/licenses/by-sa/3.0/. Any of the above conditions can be waived if you get permission from the copyright holder. Nothing in this license impairs or restricts the author's moral rights.

Art of Multiprocessor Programming

189

You might also like