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

Similar documents
A class C of objects is universal for some set E of classes if and only if any object in E can be implemented with objects of C (and registers)

Shared-Memory Computability

The Universality of Consensus

Programming Paradigms for Concurrency Lecture 3 Concurrent Objects

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

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

The Relative Power of Synchronization Methods

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

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

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

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

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

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

Spin Locks and Contention

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

Advanced Multiprocessor Programming

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

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

Sequen&al Consistency and Linearizability

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

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

Unit 6: Indeterminate Computation

k-abortable Objects: Progress under High Contention

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

What We'll Cover Today

Peterson s Algorithm

Coarse-grained and fine-grained locking Niklas Fors

Programming Paradigms for Concurrency Lecture 2 - Mutual Exclusion

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

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

6.852: Distributed Algorithms Fall, Class 21

Distributed Computing through Combinatorial Topology. Maurice Herlihy & Dmitry Kozlov & Sergio Rajsbaum

Atomic Variables & Nonblocking Synchronization

Programming Paradigms for Concurrency Introduction

Distributed Computing through Combinatorial Topology MITRO207, P4, 2017

The Wait-Free Hierarchy

Hashing and Natural Parallism. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

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

Non-blocking Array-based Algorithms for Stacks and Queues!

Introduction to Multiprocessor Synchronization

Concurrent Objects and Linearizability

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

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

Agenda. Lecture. Next discussion papers. Bottom-up motivation Shared memory primitives Shared memory synchronization Barriers and locks

Linked Lists: The Role of Locking. Erez Petrank Technion

Programming Paradigms for Concurrency Lecture 6 Synchronization of Concurrent Objects

Blocking Non-blocking Caveat:

Implementing Mutual Exclusion. Sarah Diesburg Operating Systems CS 3430

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

DD2451 Parallel and Distributed Computing --- FDD3008 Distributed Algorithms

Last Lecture: Spin-Locks

Modern High-Performance Locking

Solo-Valency and the Cost of Coordination

Mutual Exclusion: Classical Algorithms for Locks

Fast and Lock-Free Concurrent Priority Queues for Multi-Thread Systems

Building Efficient Concurrent Graph Object through Composition of List-based Set

Wait-Free Computability for General Tasks

Lock-Free, Wait-Free and Multi-core Programming. Roger Deran boilerbay.com Fast, Efficient Concurrent Maps AirMap

1) If a location is initialized to 0, what will the first invocation of TestAndSet on that location return?

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

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

Shared Objects. Shared Objects

arxiv: v1 [cs.dc] 8 May 2017

Introduction to Concurrent Programming

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

DD2451 Parallel and Distributed Computing --- FDD3008 Distributed Algorithms

A Skiplist-based Concurrent Priority Queue with Minimal Memory Contention

Ownership of a queue for practical lock-free scheduling

Section 4 Concurrent Objects Correctness, Progress and Efficiency

A Non-Blocking Concurrent Queue Algorithm

DCAS-Based Concurrent Deques

Parallel Programming

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

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

Locking Granularity. CS 475, Spring 2019 Concurrent & Distributed Systems. With material from Herlihy & Shavit, Art of Multiprocessor Programming

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

Non-blocking Array-based Algorithms for Stacks and Queues. Niloufar Shafiei

Lecture 21: Transactional Memory. Topics: consistency model recap, introduction to transactional memory

The Art of Multiprocessor Programming Copyright 2007 Elsevier Inc. All rights reserved. October 3, 2007 DRAFT COPY

Concurrent specifications beyond linearizability

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

A linear-list Data Structure where - addition of elements to and - removal of elements from are restricted to the first element of the list.

Lock-Free Techniques for Concurrent Access to Shared Objects

CS 333 Introduction to Operating Systems. Class 3 Threads & Concurrency. Jonathan Walpole Computer Science Portland State University

Parallel Programming

CS 241 Honors Concurrent Data Structures

Wait-Free Multi-Word Compare-And-Swap using Greedy Helping and Grabbing

On the Importance of Synchronization Primitives with Low Consensus Numbers

Lock-free algorithms for Kotlin coroutines. It is all about scalability Presented at SPTCC 2017 /Roman JetBrains

SPIN, PETERSON AND BAKERY LOCKS

Algorithms for Scalable Synchronization on Shared Memory Multiprocessors by John M. Mellor Crummey Michael L. Scott

Futures, Scheduling, and Work Distribution. Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Cache Coherence and Atomic Operations in Hardware

From Bounded to Unbounded Concurrency Objects and Back

Stuart

Module 7: Synchronization Lecture 13: Introduction to Atomic Primitives. The Lecture Contains: Synchronization. Waiting Algorithms.

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

9/23/2014. Concurrent Programming. Book. Process. Exchange of data between threads/processes. Between Process. Thread.

Lecture 9: Multiprocessor OSs & Synchronization. CSC 469H1F Fall 2006 Angela Demke Brown

COMP 322: Principles of Parallel Programming Lecture 11: Parallel Programming Issues (Chapter 6) Fall 2009

Transcription:

Universality of Consensus Companion slides for The by Maurice Herlihy & Nir Shavit

Turing Computability 1 0 1 1 0 1 0 A mathematical model of computation Computable = Computable on a T-Machine 2

Shared-Memory Computability cache cache cache shared memory Model of asynchronous concurrent computation Computable = Wait-free/Lock-free computable on a multiprocessor 3

Consensus Hierarchy 1 Read/Write Registers, Snapshots 2 getandset, getandincrement,... compareandset, 4

Who Implements Whom? no no no 1 Read/Write Registers, Snapshots 2 getandset, getandincrement,... compareandset, 5

Hypothesis yes? yes? yes? 1 Read/Write Registers, Snapshots 2 getandset, getandincrement,... compareandset, 6

Theorem: Universality Consensus is universal From n-thread consensus build a Wait-free Linearizable n-threaded implementation Of any sequentially specified object 7

Proof Outline A universal construction From n-consensus objects And atomic registers Any wait-free linearizable object Not a practical construction But we know where to start looking 8

Like a Turing Machine This construction Illustrates what needs to be done Optimization fodder Correctness, not efficiency Why does it work? (Asks the scientist) How does it work? (Asks the engineer) Would you like fries with that? (Asks the liberal arts major) 9

A Generic Sequential Object public interface SeqObject { public abstract Response apply(invocation invoc); 10

A Generic Sequential Object public interface SeqObject { public abstract Response apply(invocation invoc); Push:5, Pop:null 11

Invocation public class Invoc { public String method; public Object[] args; 12

Invocation public class Invoc { public String method; public Object[] args; Method name 13

Invocation public class Invoc { public String method; public Object[] args; Arguments 14

A Generic Sequential Object public interface SeqObject { public abstract Response apply(invocation invoc); 15

A Generic Sequential Object public interface SeqObject { public abstract Response apply(invocation invoc); OK, 4 16

Response public class Response { public Object value; 17

Response public class Response { public Object value; Return value 18

Universal Concurrent Object public interface SeqObject { public abstract Response apply(invocation invoc); A universal concurrent object is linearizable to the generic sequential object 19

Start with Lock-Free Universal Construction First Lock-free: infinitely often some method call finishes. Then Wait-Free: each method call takes a finite number of steps to finish 20

Naïve Idea Consensus object stores reference to cell with current state Each thread creates new cell computes outcome, tries to switch pointer to its outcome Sadly, no consensus objects can be used once only 21

Naïve Idea enq deq 22

Naïve Idea Concurrent Object enq Decide which to apply using consensus head? deq 23

Once is not Enough? Queue based consensus public T decide(t value) { propose(value); Ball ball = queue.deq(); if (ball == Ball.RED) return proposed[i]; else return proposed[1-i]; Solved one-shot 2-consensus. Not clear how to reuse or reread 24

Improved Idea: Linked-List Representation Each node contains a fresh consensus object used to decide on next operation deq tail enq enq enq 25

Universal Construction Object represented as Initial Object State A Log: a linked list of the method calls 26

Universal Construction Object represented as Initial Object State A Log: a linked list of the method calls New method call Find end of list Atomically append call Compute response by replaying log 27

Basic Idea Use one-time consensus object to decide next pointer 28

Basic Idea Use one-time consensus object to decide next pointer All threads update actual next pointer based on decision OK because they all write the same value 29

Basic Idea Threads use one-time consensus object to decide which node goes next Threads update actual next field to reflect consensus outcome OK because they all write the same value Challenges Lock-free means we need to worry what happens if a thread stops in the middle 30

Basic Data Structures public class Node implements java.lang.comparable { public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Node(Invoc invoc) { invoc = invoc; decidenext = new Consensus<Node>() seq = 0; 31

Basic Data Structures public class Node implements java.lang.comparable { public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Standard Node(Invoc interface invoc) for class { whose invoc = invoc; objects are totally ordered decidenext = new Consensus<Node>() seq = 0; 32

Basic Data Structures public class Node implements java.lang.comparable { public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Node(Invoc the invocation invoc) { invoc = invoc; decidenext = new Consensus<Node>() seq = 0; 33

Basic Data Structures public class Node implements java.lang.comparable { public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Node(Invoc invoc) { invoc = invoc; decidenext Decide = new on next Consensus<Node>() node seq (next = 0; method applied to object) 34

Basic Data Structures public class Node implements java.lang.comparable { public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Node(Invoc invoc) { invoc = invoc; decidenext Traversable = pointer new Consensus<Node>() to next node seq (needed = 0; because you cannot repeatedly read a consensus object) 35

Basic Data Structures public class Node implements java.lang.comparable { public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Node(Invoc invoc) { invoc = invoc; decidenext = new Consensus<Node>() seq = 0; Seq number 36

Basic Data Structures public Create class new Node node implements for this method java.lang.comparable { invocation public Invoc invoc; public Consensus<Node> decidenext; public Node next; public int seq; public Node(Invoc invoc) { invoc = invoc; decidenext = new Consensus<Node>() seq = 0; 37

Seq number, Invoc Universal Object next node tail 1 2 3 4 decidenext (Consensus Object) head Ptr to cell w/highest Seq Num 38

Universal Object node tail 1 2 3 head 4 All threads repeatedly modify head back to where we started? 39

The Solution head node tail 1 2 3 4 Find head by finding Max of nodes referenced by head array Make head an array i Thread i updates location i Ref to node at front 40

Universal Object public class Universal { private Node[] head; private Node tail = new Node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail 41

Universal Object public class Universal { private Node[] head; private Node tail = new Node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail Head Pointers Array 42

Universal Object public class Universal { private Node[] head; private Node tail = new Node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail Tail is a sentinel node with sequence number 1 43

Universal Object public class Universal { private Node[] head; private Node tail = new Node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail Initially head points to tail 44

Find Max Head Value public static Node max(node[] array) { Node max = array[0]; for (int i = 1; i < array.length; i++) if (max.seq < array[i].seq) max = array[i]; return max; 45

Find Max Head Value public static Node max(node[] array) { Node max = array[0]; for (int i = 0; i < array.length; i++) if (max.seq < array[i].seq) max = array[i]; return max; Traverse the array 46

Find Max Head Value public static Node max(node[] array) { Node max = array[0]; for (int i = 0; i < array.length; i++) if (max.seq < array[i].seq) max = array[i]; return max; Compare the seq nums of nodes pointed to by the array 47

Find Max Head Value public static Node max(node[] array) { Node max = array[0]; for (int i = 0; i < array.length; i++) if (max.seq < array[i].seq) max = array[i]; return max; Return node with maximal sequence number 48

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; 49

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] Apply has = after; invocation as input and returns the appropriate response 50

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] my = ID after; 51

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; My method call 52

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next As long = after; as I have not been after.seq = before.seq threaded into + 1; list head[i] = after; 53

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next Head = after; of list to which we after.seq = before.seq + 1; will try to append head[i] = after; 54

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; Propose next node 55

Universal Application public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while Set next (prefer.seq field to consensus == 0) { winner Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; 56

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); Node prefer = new node(invoc); while (prefer.seq == 0) { Set seq number Node before = Node.max(head); Node (indicating after = node was appended) before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; 57

Universal Application Part I public Response apply(invoc invoc) { int i = ThreadID.get(); add to head array so new Node prefer = new head node(invoc); will be found while (prefer.seq == 0) { Node before = Node.max(head); Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; 58

Part 2 Compute Response Red s method call tail null enq( ) enq( ) deq() Private copy of object return 59

Universal Application Part 2... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); 60

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); Compute result by sequentially applying method calls in list to a private copy 61

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); Start with copy of sequential object 62

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); new method call appended after tail 63

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); While my method call not linked 64

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); Apply current node s method 65

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); Return result after my method call applied 66

Correctness List defines linearized sequential history Thread returns its response based on list order 67

Lock-freedom Lock-free because A thread moves forward in list Can repeatedly fail to win consensus on real head only if another succeeds Consensus winner adds node and completes within a finite number of steps 68

Wait-free Construction Lock-free construction + announce array Stores (pointer to) node in announce If a thread doesn t append its node Another thread will see it in array and help append it 69

Helping Announcing my intention Guarantees progress Even if the scheduler hates me My method call will complete Makes protocol wait-free Otherwise starvation possible 70

Wait-free Construction announce tail 1 2 3 head i 4 Ref to cell thread i wants to append i 71

The Announce Array public class Universal { private Node[] announce; private Node[] head; private Node tail = new node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail; announce[j] = tail ; 72

The Announce Array public class Universal { private Node[] announce; private Node[] head; private Node tail = new node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail; announce[j] = tail ; New field: announce array 73

The Announce Array public class Universal { private Node[] announce; private Node[] head; private Node tail = new node(); tail.seq = 1; for (int j=0; j < n; j++){ head[j] = tail; announce[j] = tail ; All entries initially point to tail 74

A Cry For Help public Response apply(invoc invoc) { int i = ThreadID.get(); announce[i] = new Node(invoc); head[i] = Node.max(head); while (announce[i].seq == 0) { // while node not appended to list 75

A Cry For Help public Response apply(invoc invoc) { int i = ThreadID.get(); announce[i] = new Node(invoc); head[i] = Node.max(head); while (announce[i].seq == 0) { // while node not appended to list Announce new method call, asking help from others 76

A Cry For Help public Response apply(invoc invoc) { int i = ThreadID.get(); announce[i] = new Node(invoc); head[i] = Node.max(head); while (announce[i].seq == 0) { // while node not appended to list Look for end of list 77

A Cry For Help public Response apply(invoc invoc) { int i = ThreadID.get(); announce[i] = new Node(invoc); head[i] = Node.max(head); while (announce[i].seq == 0) { // while node not appended to list Main loop, while node not appended (either by me or helper) 78

Main Loop Non-zero sequence # means success 79

Main Loop Non-zero sequence # means success Thread keeps helping append nodes 80

Main Loop Non-zero sequence # means success Thread keeps helping append nodes Until its own node is appended 81

Main Loop while (announce[i].seq == 0) { Node before = head[i]; Node help = announce[(before.seq + 1) % n]; if (help.seq == 0) prefer = help; else prefer = announce[i]; 82

Main Loop while (announce[i].seq == 0) { Node before = head[i]; Node help = announce[(before.seq + 1) % n]; if (help.seq == 0) prefer = help; else prefer = announce[i]; Keep trying until my cell gets a sequence number 83

Main Loop while (announce[i].seq == 0) { Node before = head[i]; Node help = announce[(before.seq + 1) % n]; if (help.seq == 0) prefer = help; else prefer = announce[i]; Possible end of list 84

Main Loop while (announce[i].seq == 0) { Node before = head[i]; Node help = announce[(before.seq + 1) % n]; if (help.seq == 0) prefer = help; else prefer = announce[i]; Whom do I help? 85

Altruism Choose a thread to help 86

Altruism Choose a thread to help If that thread needs help Try to append its node Otherwise append your own 87

Altruism Choose a thread to help If that thread needs help Try to append its node Otherwise append your own Worst case Everyone tries to help same pitiful loser Someone succeeds 88

Help! When last node in list has sequence number k 89

Help! When last node in list has sequence number k All threads check Whether thread k+1 mod n wants help If so, try to append her node first 90

Help! First time after thread k+1 announces No guarantees 91

Help! First time after thread k+1 announces No guarantees After n more nodes appended Everyone sees that thread k+1 wants help Everyone tries to append that node Someone succeeds 92

Sliding Window Lemma After thread A announces its node No more than n other calls Can start and finish Without appending A s node 93

So all see and help append 4 Helping Thread 4: Help me! announce Max head +1 = n+4 4 tail 1 2 3 n+2 n+3 head 94

The Sliding Help Window 3 4 announce help 3 help 4 tail 1 2 3 n+2 n+3 head 95

Sliding Help Window while (announce[i].seq == 0) { Node before = head[i]; Node help = announce[(before.seq + 1) % n]; if (help.seq == 0) prefer = help; else prefer = announce[i]; In each main loop iteration pick another thread to help 96

Sliding Help Window Help if help required, but otherwise it s all about me! while (announce[i].seq == 0) { Node before = head[i]; Node help = announce[(before.seq + 1) % n]; if (help.seq == 0) prefer = help; else prefer = announce[i]; 97

Rest is Same as Lock-free while (announce[i].seq == 0) { Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; 98

Rest is Same as Lock-free while (announce[i].seq == 0) { Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; Call consensus to attempt to append 99

Rest is Same as Lock-free while (announce[i].seq == 0) { Node after = before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; cache consensus result for later use 100

Rest is Same as Lock-free while (announce[i].seq == 0) { Node Tell after world = that node is appended before.decidenext.decide(prefer); before.next = after; after.seq = before.seq + 1; head[i] = after; 101

Finishing the Job Once thread s node is linked 102

Finishing the Job Once thread s node is linked The rest same as lock-free algorithm 103

Finishing the Job Once thread s node is linked The rest same as lock-free algorithm Compute result by sequentially applying list s method calls to a private copy of the object starting from the initial state 104

Then Same Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= announce[i]){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); 105

Universal Application Part II... //compute my response SeqObject MyObject = new SeqObject(); current = tail.next; while (current!= prefer){ MyObject.apply(current.invoc); current = current.next; return MyObject.apply(current.invoc); Return result after applying my method 106

Shared-Memory Computability Universal 10011 Construction Wait-free/Lock-free computable = Solving n-consensus 107

Swap (getandset) not Universal public class RMWRegister { private int value; public boolean getandset(int update) { int prior = value; value = update; return prior; 108

Swap (getandset) not Universal public class RMWRegister { private int value; public boolean getandset(int update) { int prior = value; value = update; return prior; Consensus number 2 109

Swap (getandset) not Universal public class RMWRegister { private int value; public boolean getandset(int update) { int prior = value; value = update; return prior; Not universal for 3 threads 110

CompareAndSet is Universal public class RMWRegister { private int value; public boolean compareandset(int expected, int update) { int prior = value; if (value == expected) { value = update; return true; return false; 111

CompareAndSet is Universal public class RMWRegister { private int value; public boolean compareandset(int expected, int update) { int prior = value; if (value == expected) { value = update; return true; return false; Consensus number 112

CompareAndSet is Universal public class RMWRegister { private int value; public boolean compareandset(int expected, int update) { int prior = value; if (value == expected) { value = update; return true; return false; Universal for any number of threads 113

On Older Architectures IBM 360 testandset (getandset) NYU UltraComputer getandadd (fetchandadd) Neither universal Except for 2 threads 114

On Newer Architectures Intel x86, Itanium, SPARC compareandset (CAS, CMPXCHG) Alpha AXP, PowerPC Load-locked/store-conditional All universal For any number of threads Trend is clear 115

Practical Implications Any architecture that does not provide a universal primitive has inherent limitations You cannot avoid locking for concurrent data structures 116

Shared-Memory Computability Universal 10011 Object Wait-free/Lock-free computable = Threads with methods that solve n-consensus 117

Veni, Vidi, Vici We saw how to define concurrent objects 118

Veni, Vidi, Vici We saw how to define concurrent objects We discussed computational power of machine instructions 119

Veni, Vidi, Vici We saw how to define concurrent objects We discussed computational power of machine instructions Next use these foundations to understand the real world 120

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