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 = {ac,bc} S = {ab,ac,bc} 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