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

Similar documents
Programming Paradigms for Concurrency Lecture 3 Concurrent Objects

DD2451 Parallel and Distributed Computing --- FDD3008 Distributed Algorithms

10/27/11. Is The Queue Correct? Concurrent Computaton. Objects. A Concurrent FIFO Queue head. A Concurrent FIFO Queue head

Sequen&al Consistency and Linearizability

Introduction to Concurrency and Multicore Programming. Slides adapted from Art of Multicore Programming by Herlihy and Shavit

Review of last lecture. Goals of this lecture. DPHPC Overview. Lock-based queue. Lock-based queue

Review of last lecture. Peer Quiz. DPHPC Overview. Goals of this lecture. Lock-based queue

Concurrent Objects and Linearizability

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

Overview of Lecture 4. Memory Models, Atomicity & Performance. Ben-Ari Concurrency Model. Dekker s Algorithm 4

Introduction to Multiprocessor Synchronization

CONCURRENT LIBRARIES. Correctness Criteria, Verification

Lecture 7: Mutual Exclusion 2/16/12. slides adapted from The Art of Multiprocessor Programming, Herlihy and Shavit

Unit 6: Indeterminate Computation

Lecture 4: Languages, Fast Locks, and Lock-free

The Relative Power of Synchronization Methods

Review of last lecture. Peer Quiz. DPHPC Overview. Goals of this lecture. Is coherence everything?

Solution: a lock (a/k/a mutex) public: virtual void unlock() =0;

The Universality of Consensus

Temporal Logic of Actions (TLA) (a brief introduction) Shmuel Katz Computer Science Department The Technion

Foundations of the C++ Concurrency Memory Model

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

Relaxed Memory-Consistency Models

CSE 613: Parallel Programming. Lecture 17 ( Concurrent Data Structures: Queues and Stacks )

Models of concurrency & synchronization algorithms

Memory Consistency Models

Blocking Non-blocking Caveat:

The Wait-Free Hierarchy

CS510 Advanced Topics in Concurrency. Jonathan Walpole

DISTRIBUTED COMPUTER SYSTEMS

CMSC 330: Organization of Programming Languages. Threads Classic Concurrency Problems

Section 4 Concurrent Objects Correctness, Progress and Efficiency

Story so far. Parallel Data Structures. Parallel data structure. Working smoothly with Galois iterators

Parallel Computer Architecture Spring Memory Consistency. Nikos Bellas

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

Consistency. CS 475, Spring 2018 Concurrent & Distributed Systems

The New Java Technology Memory Model

CMSC 330: Organization of Programming Languages. The Dining Philosophers Problem

Mutual Exclusion: Classical Algorithms for Locks

Lecture 27: Safety and Liveness Properties, Java Synchronizers, Dining Philosophers Problem

CS5460: Operating Systems

Symmetric Multiprocessors: Synchronization and Sequential Consistency

Important Lessons. A Distributed Algorithm (2) Today's Lecture - Replication

Spin Locks and Contention. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Linearizability of Persistent Memory Objects

Quasi-Linearizability Relaxed Consistency For Improved Concurrency

Cache-Aware Lock-Free Queues for Multiple Producers/Consumers and Weak Memory Consistency

Programming Paradigms for Concurrency Lecture 2 - Mutual Exclusion

Mutual Exclusion. 1 Formal problem definitions. Time notion CSE /17/2015. Outline of this lecture:

CS 241 Honors Concurrent Data Structures

Concurrent Queues, Monitors, and the ABA problem. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

1 The comparison of QC, SC and LIN

Linked Lists: Locking, Lock-Free, and Beyond. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Chapter 6: Process [& Thread] Synchronization. CSCI [4 6] 730 Operating Systems. Why does cooperation require synchronization?

SPIN, PETERSON AND BAKERY LOCKS

NON-BLOCKING DATA STRUCTURES AND TRANSACTIONAL MEMORY. Tim Harris, 28 November 2014

Thread-Local. Lecture 27: Concurrency 3. Dealing with the Rest. Immutable. Whenever possible, don t share resources

Typed Assembly Language for Implementing OS Kernels in SMP/Multi-Core Environments with Interrupts

Order Is A Lie. Are you sure you know how your code runs?

Sharing Objects Ch. 3

Ownership of a queue for practical lock-free scheduling

! Why is synchronization needed? ! Synchronization Language/Definitions: ! How are locks implemented? Maria Hybinette, UGA

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

Shared-Memory Computability

The Java Memory Model

A Non-Blocking Concurrent Queue Algorithm

Consistency: Strict & Sequential. SWE 622, Spring 2017 Distributed Software Engineering

k-abortable Objects: Progress under High Contention

The Java Memory Model

Memory Consistency Models: Convergence At Last!

Synchronising Threads

A simple correctness proof of the MCS contention-free lock. Theodore Johnson. Krishna Harathi. University of Florida. Abstract

Programming Language Seminar Concurrency 2: Lock-free algorithms

COMP Parallel Computing. CC-NUMA (2) Memory Consistency

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

Spin Locks and Contention

CSE 374 Programming Concepts & Tools

Spin Locks and Contention. Companion slides for Chapter 7 The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Thread Synchronization: Too Much Milk

Whatever can go wrong will go wrong. attributed to Edward A. Murphy. Murphy was an optimist. authors of lock-free programs LOCK FREE KERNEL

Consistency: Relaxed. SWE 622, Spring 2017 Distributed Software Engineering

CS 31: Introduction to Computer Systems : Threads & Synchronization April 16-18, 2019

Shared Objects. Shared Objects

6.852: Distributed Algorithms Fall, Class 21

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

Synchronization. CS61, Lecture 18. Prof. Stephen Chong November 3, 2011

Indistinguishability: Friend and Foe of Concurrent Data Structures. Hagit Attiya CS, Technion

Using Relaxed Consistency Models

CSE332: Data Abstractions Lecture 22: Shared-Memory Concurrency and Mutual Exclusion. Tyler Robison Summer 2010

G Programming Languages Spring 2010 Lecture 13. Robert Grimm, New York University

Introduction. Coherency vs Consistency. Lec-11. Multi-Threading Concepts: Coherency, Consistency, and Synchronization

Safety and liveness for critical sections

CMSC 330: Organization of Programming Languages. Concurrency & Multiprocessing

Spin Locks and Contention. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Concurrency & Parallelism. Threads, Concurrency, and Parallelism. Multicore Processors 11/7/17

NOW Handout Page 1. Memory Consistency Model. Background for Debate on Memory Consistency Models. Multiprogrammed Uniprocessor Mem.

DD2451 Parallel and Distributed Computing --- FDD3008 Distributed Algorithms

Chapter 6: Process Synchronization

Peterson s Algorithm

Lecture 32: Volatile variables, Java memory model

Transcription:

Concurrent Objects Companion slides for The by Maurice Herlihy & Nir Shavit

Concurrent Computation memory object object 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? 3

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

FIFO Queue: Enqueue Method q.enq( ) 5

FIFO Queue: Dequeue Method q.deq()/ 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]; } 7

A Lock-Based Queue head 0 1 capacity-1 class LockBasedQueue<T> { y z 2 int head, tail; T[] items; Lock lock; public LockBasedQueue(int capacity) { head = 0; tail = 0; lock = new ReentrantLock(); items = (T[]) new Object[capacity]; } tail Queue fields protected by single shared lock 8

A Lock-Based Queue head 0 1 capacity-1 class LockBasedQueue<T> { y z 2 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 tail 9

Implementation: Deq head 0 1 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(); } } 2 tail 10

Implementation: Deq 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(); } head 0 1 Method calls mutually exclusive 2 tail 11

Implementation: Deq 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(); } head 0 1 If queue empty throw exception 2 tail 12

Implementation: Deq 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(); } head 0 1 Queue not empty: remove item and update head 2 tail 13

Implementation: Deq head 0 1 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(); } } Return result 2 tail 14

Implementation: Deq 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(); } head 0 1 Release lock no matter what! 2 tail 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(); } } 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 17

Wait-free 2-Thread Queue public class WaitFreeQueue { int head = 0, tail = 0; items = (T[]) new Object[capacity]; public void enq(item x) { while (tail-head == capacity); // busy-wait items[tail % capacity] = x; tail++; } public Item deq() { while (tail == head); // busy-wait Item item = items[head % capacity]; head++; return item; }} 18

Wait-free 2-Thread Queue public class LockFreeQueue { int head = 0, tail = 0; items = (T[]) new Object[capacity]; head capacity-1 0 1 y z 2 tail public void enq(item x) { while (tail-head == capacity); // busy-wait items[tail % capacity] = x; tail++; } public Item deq() { while (tail == head); // busy-wait Item item = items[head % capacity]; head++; return item; }} 19

Lock-free 2-Thread Queue public class LockFreeQueue { int head = 0, tail = 0; items = (T[])new Object[capacity]; head capacity-1 0 1 y z 2 tail public void enq(item x) { while (tail-head == capacity); // busy-wait items[tail % capacity] = x; tail++; } public Item deq() { while (tail == head); // busy-wait Item item = items[head % capacity]; head+ +; return Queue item; is updated without a lock! }} 20

Defining concurrent queue implementations Need a way to specify a concurrent queue object Need a way to prove that an algorithm implements the object s specification Lets talk about object specifications 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 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 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, con t) the object will be in some other state when the method returns, 24

Pre and PostConditions for Dequeue Precondition: Queue is non-empty Postcondition: Returns first item in queue Postcondition: Removes first item in queue 25

Pre and PostConditions for Dequeue Precondition: Queue is empty Postcondition: Throws Empty exception Postcondition: Queue state unchanged 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 27

What About Concurrent Specifications? Methods? Documentation? Adding new methods? 28

Methods Take Time time 29

Methods Take Time invocation 12:00 q.enq (...) time 30

Methods Take Time invocation 12:00 q.enq (...) Method call time 31

Methods Take Time invocation 12:00 q.enq (...) Method call time 32

Methods Take Time invocation 12:00 response 12:01 q.enq (...) void Method call time 33

Sequential vs Concurrent Sequential Methods take time? Who knew? Concurrent Method call is not an event Method call is an interval. 34

Concurrent Methods Take Overlapping Time time 35

Concurrent Methods Take Overlapping Time Method call time 36

Concurrent Methods Take Overlapping Time Method call Method call time 37

Concurrent Methods Take Overlapping Time Method call Method call Method call time 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 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? 40

Sequential vs Concurrent Sequential: Can add new methods without affecting older methods Concurrent: Everything can potentially interact with everything else 41

Sequential vs Concurrent Sequential: Can add new methods without affecting older methods Concurrent: Everything can potentially interact with everything else 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 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(); } } 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 { lock.unlock(); } All modifications of queue are done mutually exclusive 45

Intuitively Lets capture the idea of describing the concurrent via the sequential lock() q.deq unlock() q.enq deq lock() enq unlock() Behavior is Sequential 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 Ordering must be maintained between request and responses (addendum) Any such concurrent object is Linearizable 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 48

Example time (6) 49

Example q.enq(x) time (6) 50

Example q.enq(x) q.enq(y) time (6) 51

Example q.enq(x) q.enq(y) q.deq(x) time (6) 52

Example q.enq(x) q.deq(y) q.enq(y) q.deq(x) time (6) 53

Example q.enq(x) q.deq(y) q.enq(y) q.deq(x) time (6) 54

Example q.enq(x) q.deq(y) q.enq(y) q.deq(x) time (6) 55

Example time (5) 56

Example q.enq(x) time (5) 57

Example q.enq(x) q.deq(y) time (5) 58

Example q.enq(x) q.deq(y) q.enq(y) time (5) 59

Example q.enq(x) q.deq(y) q.enq(y) time (5) 60

Example q.enq(x) q.deq(y) q.enq(y) time (5) 61

Example time (4) 62

Example q.enq(x) time (4) 63

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

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

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

Example q.enq(x) time (8) 67

Example q.enq(x) q.enq(y) time (8) 68

Example q.enq(x) q.deq(y) q.enq(y) time (8) 69

Example q.enq(x) q.deq(y) q.enq(y) q.deq(x) time (8) 70

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

Read/Write Register Example write(0) read(1) write(2) write(1) read(0) time (4) 72

Read/Write Register Example write(0) read(1) write(2) write(1) already happened write(1) time read(0) (4) 73

Read/Write Register Example write(0) read(1) write(2) write(1) already happened write(1) time read(0) (4) 74

Read/Write Register Example write(0) read(1) write(2) write(1) already happened write(1) time read(0) (4) 75

Read/Write Register Example write(0) read(1) write(2) write(1) already happened write(1) time read(1) (4) 76

Read/Write Register Example write(0) read(1) write(2) write(1) already happened write(1) time read(1) (4) 77

Read/Write Register Example write(0) read(1) write(2) write(1) already happened write(1) time read(1) (4) 78

Read/Write Register Example write(0) write(2) write(1) read(1) time (4) 79

Read/Write Register Example write(0) write(2) write(1) read(1) time (4) 80

Read/Write Register Example write(0) write(2) write(1) read(1) time (4) 81

Read/Write Register Example write(0) read(1) write(2) write(1) read(1) time (2) 82

Read/Write Register Example write(0) read(1) write(2) write(1) read(1) time (2) 83

Read/Write Register Example write(0) read(1) write(2) write(1) read(1) time (2) 84

Read/Write Register Example write(0) read(1) write(2) write(1) read(2) time (2) 85

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 86

Formal Model of Executions Define precisely what we mean Ambiguity is bad when intuition is weak Allow reasoning 87

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 88

Invocation Notation A q.enq(x) (4) 89

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

Invocation Notation A q.enq(x) thread method (4) 91

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

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

Response Notation A q: void (2) 94

Response Notation A q: void thread (2) 95

Response Notation A q: void thread result (2) 96

Response Notation A q: void thread result object (2) 97

Response Notation A q: void thread result object (2) 98

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

History - Describing an Execution H = A q.enq(3) A q:void A q.enq(5) B p.enq(4) B p:void B q.deq() B q:3 Sequence of invocations and responses 100

Definition Invocation & response match if Thread names agree A q.enq(3) A q:void Object names agree Method call (1) 101

Object Projections H = A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 102

Object Projections H q = A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 103

Thread Projections H = A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 104

Thread Projections H B = A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 105

Complete Subhistory H = A q.enq(3) A q:void A q.enq(5) B p.enq(4) B p:void B q.deq() An invocation is B q:3 pending if it has no matching respnse 106

Complete Subhistory H = A q.enq(3) A q:void A q.enq(5) B p.enq(4) B p:void B q.deq() B q:3 May or may not have taken effect 107

Complete Subhistory H = A q.enq(3) A q:void A q.enq(5) B p.enq(4) B p:void B q.deq() B q:3 discard pending invocations 108

Complete Subhistory A q.enq(3) A q:void Complete(H) = B p.enq(4) B p:void B q.deq() B q:3 109

Sequential Histories A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 A q:enq(5) (4) 110

Sequential Histories A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 A q:enq(5) match (4) 111

Sequential Histories A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 A q:enq(5) match match (4) 112

Sequential Histories A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 A q:enq(5) match match match (4) 113

Sequential Histories A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 A q:enq(5) (4) match match match Final pending invocation OK 114

Sequential Histories A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 A q:enq(5) (4) match match match Final pending invocation OK 115

Well-Formed Histories H= A q.enq(3) B p.enq(4) B p:void B q.deq() A q:void B q:3 116

Well-Formed Histories Per-thread projections sequential H= A q.enq(3) B p.enq(4) B p:void B q.deq() A q:void B q:3 H B= B p.enq(4) B p:void B q.deq() B q:3 117

Well-Formed Histories Per-thread projections sequential H= A q.enq(3) B p.enq(4) B p:void B q.deq() A q:void B q:3 H B= H A= B p.enq(4) B p:void B q.deq() B q:3 A q.enq(3) A q:void 118

Equivalent Histories Threads see the same thing in both H A = G A H B = G B H= A q.enq(3) B p.enq(4) B p:void B q.deq() A q:void B q:3 G= A q.enq(3) A q:void B p.enq(4) B p:void B q.deq() B q:3 119

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 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 121

Precedence A q.enq(3) B p.enq(4) B p.void A q:void B q.deq() B q:3 A method call precedes another if response event precedes invocation event Method call Method call (1) 122

Non-Precedence A q.enq(3) B p.enq(4) B p.void B q.deq() A q:void B q:3 Some method calls overlap one another Method call Method call (1) 123

Notation Given History H method executions m 0 and m 1 in H We say m 0 H m 1, if m 0 precedes m 1 m Relation m 0 H m 1 is a 0 m 1 Partial order Total order if H is sequential 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 So that G is equivalent to Legal sequential history S where G S 125

What is G S G = {a c,b c} S = {a b,a c,b c} a b G c time S (8) 126

Remarks Some pending invocations Took effect, so keep them Discard the rest Condition G S Means that S respects real-time order of G 127

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

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

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

Example discard this one A q.enq(3) B q.enq(4) B q:void B q.deq() B q:4 B q:enq(6) A q:void B.q.enq(3) B.q.enq(4) B.q.deq(4) B. q.enq(6) time 131

Example discard this one A q.enq(3) B q.enq(4) B q:void B q.deq() B q:4 A q:void B.q.enq(3) B.q.enq(4) B.q.deq(4) time 132

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

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

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

Concurrency How much concurrency does linearizability allow? When must a method invocation block? 136

Concurrency Focus on total methods Defined in every state Example: deq() that throws Empty exception Versus deq() that waits Why? Otherwise, blocking unrelated to synchronization 137

Concurrency Question: When does linearizability require a method invocation to block? Answer: never. Linearizability is non-blocking 138

Non-Blocking Theorem If method invocation A q.inv( ) is pending in history H, then there exists a response A q:res( ) such that H + A q:res( ) is linearizable 139

Proof Pick linearization S of H If S already contains Invocation A q.inv( ) and response, Then we are done. Otherwise, pick a response such that S + A q.inv( ) + A q:res( ) Possible because object is total. 140

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

Why Does Composability Matter? Modularity Can prove linearizability of objects in isolation Can compose independently-implemented objects 142

Reasoning About Lineraizability: Locking head 0 1 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(); } } 2 tail 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 { lock.unlock(); } Linearization points are when locks are released 144

More Reasoning: Lock-free public class LockFreeQueue { int head = 0, tail = 0; items = (T[]) new Object[capacity]; head capacity-1 0 1 y z 2 tail public void enq(item x) { while (tail-head == capacity); // busy-wait items[tail % capacity] = x; tail++; } public Item deq() { while (tail == head); // busy-wait Item item = items[head % capacity]; head++; return item; }} 145

More Reasoning public class LockFreeQueue { Linearization order is order head and tail fields modified int head = 0, tail = 0; items = (T[]) new Object[capacity]; public void enq(item x) { while (tail-head == capacity); // busy-wait items[tail % capacity] = x; tail++; } public Item deq() { while (tail == head); // busy-wait Item item = items[head % capacity]; head++; return item; }} 146

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 147

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 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 So that G is equivalent to a Legal sequential history S Where G S Differs from linearizability

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

Example time (5)

Example q.enq(x) time (5)

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

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

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

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

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

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

FIFO Queue Example p.enq(x) q.enq(x) p.deq(y) time

FIFO Queue Example p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

FIFO Queue Example p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) History H time

H p Sequentially Consistent p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

H q Sequentially Consistent p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

Ordering imposed by p p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

Ordering imposed by q p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

Ordering imposed by both p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

Combining orders p.enq(x) q.enq(x) p.deq(y) q.enq(y) p.enq(y) q.deq(x) time

Fact Most hardware architectures don t support sequential consistency Because they think it s too strong Here s another story

The Flag Example x.write(1) y.read(0) y.write(1) x.read(0) time

The Flag Example x.write(1) y.read(0) y.write(1) x.read(0) Each thread s view is sequentially consistent It went first time

The Flag Example x.write(1) y.read(0) y.write(1) x.read(0) Entire history isn t sequentially consistent time Can t both go first

The Flag Example x.write(1) y.read(0) y.write(1) x.read(0) Is this behavior really so wrong? We can argue either way time

Opinion1: It s Wrong This pattern Write mine, read yours Heart of mutual exclusion Peterson Bakery, etc. It s non-negotiable!

Opinion2: But It Should be Allowed 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

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

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

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.

Bottomline.. 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?

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

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

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

Real-World Hardware Memory Weaker than sequential consistency Examples: TSO, RMO, Intel x86 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

Critical Sections Easy way to implement linearizability Take sequential object Make each method a critical section Problems Blocking No concurrency

Linearizability Linearizability Operation takes effect instantaneously between invocation and response Uses sequential specification, locality implies composablity Good for high level objects

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

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?

Maximal vs. Minimal Minimal progress: in some suffix of H, some pending active invocation has a matching response (some method call eventually completes ).

Maximal vs. Minimal Minimal progress: in some suffix of H, some pending active invocation has a matching response (some method call eventually completes ).

Maximal vs. Minimal Minimal progress: in some suffix of H, some pending active invocation has a matching response (some method call eventually completes ). Maximal progress: in every suffix of H, every pending active invocation has a matching response (every method call always completes).

Maximal vs. Minimal Minimal progress: in some suffix of H, some pending active invocation has a matching response (some method call eventually completes ). Maximal progress: in every suffix of H, every pending active invocation has a matching response (every method call always completes).

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.

Progress Conditions Non-Blocking Blocking Everyone makes progress Someone makes progress Wait-free Lock-free Starvation-free Deadlock-free

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