The Relative Power of Synchronization Operations

Slides:



Advertisements
Similar presentations
The Relative Power of Synchronization Operations Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Advertisements

Mutual Exclusion – SW & HW By Oded Regev. Outline: Short review on the Bakery algorithm Short review on the Bakery algorithm Black & White Algorithm Black.
1 © R. Guerraoui The Limitations of Registers R. Guerraoui Distributed Programming Laboratory.
1 Chapter 4 Synchronization Algorithms and Concurrent Programming Gadi Taubenfeld © 2014 Synchronization Algorithms and Concurrent Programming Synchronization.
CSE 486/586, Spring 2012 CSE 486/586 Distributed Systems Consensus Steve Ko Computer Sciences and Engineering University at Buffalo.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Mutual Exclusion By Shiran Mizrahi. Critical Section class Counter { private int value = 1; //counter starts at one public Counter(int c) { //constructor.
Background Concurrent access to shared data can lead to inconsistencies Maintaining data consistency among cooperating processes is critical What is wrong.
Multiprocessor Synchronization Algorithms ( ) Lecturer: Danny Hendler The Mutual Exclusion problem.
Process Synchronization. Module 6: Process Synchronization Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores.
1 Operating Systems, 122 Practical Session 5, Synchronization 1.
Universality of Consensus The Art of Multiprocessor Programming Spring 2007.
CPSC 668Set 18: Wait-Free Simulations Beyond Registers1 CPSC 668 Distributed Algorithms and Systems Fall 2006 Prof. Jennifer Welch.
Introduction Companion slides for
The Relative Power of Synchronization Operations The Art of Multiprocessor Programming Spring 2007.
Foundations of Shared Memory Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS.
Shared Counters and Parallelism Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
The Relative Power of Synchronization Operations Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Concurrent Skip Lists.
Art of Multiprocessor Programming 1 Universality of Consensus Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Two-Process Systems TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: A A AA Companion slides for Distributed Computing.
Distributed Consensus Reaching agreement is a fundamental problem in distributed computing. Some examples are Leader election / Mutual Exclusion Commit.
Multicore Programming
Linearizability By Mila Oren 1. Outline  Sequential and concurrent specifications.  Define linearizability (intuition and formal model).  Composability.
Universality of Consensus and The Nature of Progress Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
CSCE 668 DISTRIBUTED ALGORITHMS AND SYSTEMS Fall 2011 Prof. Jennifer Welch CSCE 668 Set 18: Wait-Free Simulations Beyond Registers 1.
Consensus and Its Impossibility in Asynchronous Systems.
1 Chapter 9 Synchronization Algorithms and Concurrent Programming Gadi Taubenfeld © 2014 Synchronization Algorithms and Concurrent Programming Synchronization.
1 Consensus Hierarchy Part 1. 2 Consensus in Shared Memory Consider processors in shared memory: which try to solve the consensus problem.
DISTRIBUTED ALGORITHMS AND SYSTEMS Spring 2014 Prof. Jennifer Welch CSCE
CS294, Yelick Consensus revisited, p1 CS Consensus Revisited
1 Consensus Hierarchy Part 2. 2 FIFO (Queue) FIFO Object headtail.
Concurrent Queues Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Programming Language Basics Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Multiprocessor Architecture Basics Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Concurrent Skip Lists.
Fault tolerance and related issues in distributed computing Shmuel Zaks GSSI - Feb
1 Critical Section Problem CIS 450 Winter 2003 Professor Jinhua Guo.
The Relative Power of Synchronization Operations Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Concurrent Skip Lists.
Distributed Algorithms (22903)
When Is Agreement Possible
Concurrent Objects Companion slides for
Atomic Operations in Hardware
Atomic Operations in Hardware
Concurrent Objects Companion slides for
CSCE 668 DISTRIBUTED ALGORITHMS AND SYSTEMS
Computing with anonymous processes
Algebraic Topology and Distributed Computing part two
Byzantine-Resilient Colorless Computaton
The Relative Power of Synchronization Operations
Universality of Consensus
CSCE 668 DISTRIBUTED ALGORITHMS AND SYSTEMS
Alternating Bit Protocol
Simulations and Reductions
Universality of Consensus
Combinatorial Topology and Distributed Computing
Distributed Algorithms (22903)
Java Concurrency 17-Jan-19.
The Relative Power of Synchronization Methods
CSCE 668 DISTRIBUTED ALGORITHMS AND SYSTEMS
Java Concurrency.
CS333 Intro to Operating Systems
Java Concurrency.
Programming with Shared Memory Specifying parallelism
GPU Scheduling on the NVIDIA TX2:
Java Concurrency 29-May-19.
Nir Shavit Multiprocessor Synchronization Spring 2003
The Relative Power of Synchronization Operations
Presentation transcript:

The Relative Power of Synchronization Operations Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

Wait-Free Implementation Every method call completes in finite number of steps Implies no mutual exclusion We looked at wait-free implementations because they imply no mutual exclusion. (2) Art of Multiprocessor Programming

Rationale for wait-freedom We wanted atomic registers to implement mutual exclusion So we couldn’t use mutual exclusion to implement atomic registers But wait, there’s more! Art of Multiprocessor Programming

Basic Questions Wait-Free synchronization might be a good idea in principle But how do you do it Systematically? Correctly? Efficiently? Art of Multiprocessor Programming

FIFO Queue: Enqueue Method q.enq( ) Art of Multiprocessor Programming

FIFO Queue: Dequeue Method q.deq()/ Art of Multiprocessor Programming

Two-Thread Wait-Free Queue public class LockFreeQueue { int head = 0, tail = 0; Item[QSIZE] items; public void enq(Item x) { while (tail-head == QSIZE) {}; items[tail % QSIZE] = x; tail++; } public Item deq() { while (tail-head == 0) {} Item item = items[head % QSIZE]; head++; return item; }} Art of Multiprocessor Programming

What About Multiple Dequeuers? Art of Multiprocessor Programming

Grand Challenge Only new aspect Implement a FIFO queue Wait-free Linearizable From atomic read-write registers Multiple dequeuers (1) Art of Multiprocessor Programming

Consensus While you are ruminating on the grand challenge… We will give you another puzzle Consensus Will be important … Art of Multiprocessor Programming

Consensus: Each Thread has a Private Input 19 32 21 Art of Multiprocessor Programming

They Communicate Art of Multiprocessor Programming

They Agree on One Thread’s Input 19 19 19 Art of Multiprocessor Programming

Formally: Consensus Consistent: all threads decide the same value Valid: the common decision value is some thread's input As we will see later consensus can be formulated as a linearizable object in which threads in the sequential execution decide on the value of the first thread to complete. Art of Multiprocessor Programming

No Wait-Free Implementation of Consensus using Registers ??? ??? Art of Multiprocessor Programming

Formally Theorem [adapted from Fischer, Lynch, Paterson]: There is no wait- free implementation of n-thread consensus, n>1, from read-write registers Implication: asynchronous computability fundamentally different from Turing computability This is one of the most fundamental theorems of distributed computing, proved originally by Fischer, Lynch, and Paterson in the 1980’s. It says that there are problems that are easily solvable by reading and writing to memory on a single processor, a turing machine, but are not solvable on a multiprocessor. As we will see, this will have profound implications on multiprocessor hardware design. We will give here a proof of their theorem in the context of shared memory as proven by Herlihy. Art of Multiprocessor Programming

Proof Strategy Assume otherwise Reason about the properties of any such protocol Derive a contradiction Quod Erat Demonstrandum Suffices to prove for binary consensus and n=2 Art of Multiprocessor Programming

Wait-Free Computation A moves B moves Either A or B “moves” Moving means Register read Register write It suffices to prove the claim for two threads. Here is how we model computation histories. Art of Multiprocessor Programming

The Two-Move Tree Final states Initial state (2) Art of Multiprocessor Programming

Decision Values 1 1 1 1 Art of Multiprocessor Programming

Bivalent: Both Possible 1 1 1 1 Art of Multiprocessor Programming

Univalent: Single Value Possible 1 1 1 1 Art of Multiprocessor Programming

x-valent: x Only Possible Decision 1 1 1 1 Art of Multiprocessor Programming

Summary Wait-free computation is a tree Bivalent system states Outcome not fixed Univalent states Outcome is fixed May not be “known” yet 1-Valent and 0-Valent states Art of Multiprocessor Programming

Claim Some initial state is bivalent Outcome depends on Chance Whim of the scheduler Multiprocessor gods do play dice … Lets prove this claim Art of Multiprocessor Programming

Univalent: all executions must decide 0 Both Inputs 0 Univalent: all executions must decide 0 (2) Art of Multiprocessor Programming (1)

Including this solo execution by A Both Inputs 0 Including this solo execution by A (1) Art of Multiprocessor Programming (1)

All executions must decide 1 Both Inputs 1 1 1 All executions must decide 1 (2) Art of Multiprocessor Programming (1)

Including this solo execution by B Both Inputs 1 1 Including this solo execution by B (1) Art of Multiprocessor Programming (1)

What if inputs differ? 1 By Way of contradiction: If univalent 1 Imagine that all the executions still decide on one input or another…assume the claim is false and lets show the set of possible executions must then include two executions with different values. By Way of contradiction: If univalent all executions must decide on same value (2) Art of Multiprocessor Programming

The Possible Executions 1 Include the solo execution by A that decides 0 (2) Art of Multiprocessor Programming

The Possible Executions 1 Also include the solo execution by B which we know decides 1 (2) Art of Multiprocessor Programming

Possible Executions Include How univalent is that? (QED) 1 Since e Solo execution by A must decide 0 Solo execution by B must decide 1 Art of Multiprocessor Programming

Critical States critical 0-valent 1-valent A critical state is a bivalent state in which the next step by one thread will lead to a 0-valent state and the next step by the other will lead to a 1-valent state 0-valent 1-valent (3) Art of Multiprocessor Programming (3)

From a Critical State c 0-valent 1-valent If A goes first, protocol decides 0 If B goes first, protocol decides 1 Art of Multiprocessor Programming

Reaching Critical State initially bivalent CB univalent CA CB univalent CA univalent Why must there be such a critical state? Start from a bivalent state. If it is not critical, run A until about to make state 0-valent, if not a critical state, that is, if B’s step will not take the state to a 1-valent state, then run B until in is about to take system to a 1-valent state. If this state is not critical, run A again, then B, and so on. Since this is a wai-free execution, within a finite number of steps each will finish, so somewhere before they must reach a critical state. c univalent 0-valent 1-valent Art of Multiprocessor Programming

Critical States Starting from a bivalent initial state The protocol can reach a critical state Otherwise we could stay bivalent forever And the protocol is not wait-free Art of Multiprocessor Programming

Model Dependency So far, memory-independent! True for Registers Message-passing Carrier pigeons Any kind of asynchronous computation Art of Multiprocessor Programming

Read-Write Memory Reads and/or writes To same/different registers Art of Multiprocessor Programming

Completing the Proof Lets look at executions that: Start from a critical state Threads cause state to become univalent by reading or writing to same/different registers End within a finite number of steps deciding either 0 or 1 Show this leads to a contradiction Art of Multiprocessor Programming

Possible Interactions A reads x x.read() y.read() x.write() y.write() ? A reads y Tp prove that we cannot solve consensus using read-write registers, lets go over all the possible interactions among the threads and show that for each such execution they lead to a contradiction. Art of Multiprocessor Programming

Some Thread Reads Contradiction c 1 A runs solo, eventually decides 0 B reads x A runs solo, eventually decides 1 1 Contradiction This is the case in which some thread reads (and the other either reads or writes). Two possible executions, one in which A runs solo and decides 0 and another in which A runs after B takes its critical read step. Leads to a contradiction since A cannot tell that B has read…so two executions lead to the same state but the system is supposed to have two different valencies for it, a contradiction. States look the same to A Art of Multiprocessor Programming

Possible Interactions x.read() y.read() x.write() y.write() no ? Art of Multiprocessor Programming

Writing Distinct Registers A writes y B writes x A writes y B writes x Contradiction 1 The song is the same Art of Multiprocessor Programming

Possible Interactions x.read() y.read() x.write() y.write() no ? Art of Multiprocessor Programming

Writing Same Registers c B writes x A writes x A runs solo, eventually decides 0 A writes x Contradiction A runs solo, eventually decides 1 1 States look the same to A Art of Multiprocessor Programming

That’s All, Folks! QED no Art of Multiprocessor Programming x.read() y.read() x.write() y.write() no QED Art of Multiprocessor Programming

Recap: Atomic Registers Can’t Do Consensus If protocol exists It has a bivalent initial state Leading to a critical state What’s up with the critical state? Case analysis for each pair of methods As we showed, all lead to a contradiction Art of Multiprocessor Programming

What Does Consensus have to do with Concurrent Objects? Consensus can be formulated as a linearizable object in which threads in the sequential execution decide on the value of the first thread to complete. Art of Multiprocessor Programming

Consensus Object public interface Consensus { Object decide(Object value); } (4) Art of Multiprocessor Programming (4)

Concurrent Consensus Object We consider only one time objects: each thread can execute a method only once Linearizable to sequential consensus object in which the thread who’s input was decided on completed its method first A linearizable object in which threads in the sequential execution decide on the value of the first thread to complete. The consensus objects we will consider will be one time objects, that is, each thread executes a method once. Art of Multiprocessor Programming

Java Jargon Watch Define Consensus protocol as an abstract class We implement some methods Leave you to do the rest … Art of Multiprocessor Programming

Generic Consensus Protocol abstract class ConsensusProtocol implements Consensus { protected Object[] proposed = new Object[N]; private void propose(Object value) { proposed[ThreadID.get()] = value; } abstract public Object decide(object value); }} Note the use of a protected for proposed. A protected method is visible to inheriting classes, even not part of the same package. A package scope (default) method is not. That is the only difference between protected and package scope. method are restricted in accessing it. See example below: package one; public class A { protected int p; } //////////////////////////////// package two; import one. A; class B extends A void myMethod() p = 1; // ok A a = new A(); a.p = 1; // not ok, p would have to be public for this to work. (4) Art of Multiprocessor Programming (4)

Generic Consensus Protocol abstract class ConsensusProtocol implements Consensus { protected Object[] proposed = new Object[N]; private void propose(Object value) { proposed[ThreadID.get()] = value; } abstract public Object decide(object value); }} Each thread’s proposed value (4) Art of Multiprocessor Programming (4)

Generic Consensus Protocol abstract class ConsensusProtocol implements Consensus { protected Object[] proposed = new Object[N]; private void propose(Object value) { proposed[ThreadID.get()] = value; } abstract public Object decide(object value); }} Propose a value (4) Art of Multiprocessor Programming (4)

Generic Consensus Protocol abstract class ConsensusProtocol implements Consensus { protected Object[] proposed = new Object[N]; private void propose(Object value) { proposed[ThreadID.get()] = value; } abstract public Object decide(object value); }} Decide a value: abstract method means subclass does the heavy lifting (real work) (4) Art of Multiprocessor Programming (4)

Can a FIFO Queue Implement Consensus?

FIFO Queue with red and black balls FIFO Consensus proposed array FIFO Queue with red and black balls 8 Coveted red ball Dreaded black ball Art of Multiprocessor Programming

Protocol: Write Value to Array 1 Art of Multiprocessor Programming

Protocol: Take Next Item from Queue 8 1 Art of Multiprocessor Programming

Protocol: Take Next Item from Queue I got the dreaded black ball, so I will decide the other’s value from the array I got the coveted red ball, so I will decide my value 1 8 Art of Multiprocessor Programming

Consensus Using FIFO Queue public class QueueConsensus extends ConsensusProtocol { private Queue queue; public QueueConsensus() { queue = new Queue(); queue.enq(Ball.RED); queue.enq(Ball.BLACK); } … Art of Multiprocessor Programming

Initialize Queue public class QueueConsensus extends ConsensusProtocol { private Queue queue; public QueueConsensus() { this.queue = new Queue(); this.queue.enq(Ball.RED); this.queue.enq(Ball.BLACK); } … 8 Art of Multiprocessor Programming

Who Won? public class QueueConsensus extends ConsensusProtocol { private Queue queue; … public decide(object value) { propose(value); Ball ball = this.queue.deq(); if (ball == Ball.RED) return proposed[i]; else return proposed[1-i]; } Art of Multiprocessor Programming

Race to dequeue first queue item Who Won? public class QueueConsensus extends ConsensusProtocol { private Queue queue; … public decide(object value) { propose(value); Ball ball = this.queue.deq(); if (ball == Ball.RED) return proposed[i]; else return proposed[1-ij]; } Race to dequeue first queue item Art of Multiprocessor Programming

Who Won? I win if I was first public class QueueConsensus extends ConsensusProtocol { private Queue queue; … public decide(object value) { propose(value); Ball ball = this.queue.deq(); if (ball == Ball.RED) return proposed[i]; else return proposed[1-i]; } i = ThreadID.get(); I win if I was first Art of Multiprocessor Programming

Other thread wins if I was second Who Won? public class QueueConsensus extends ConsensusProtocol { private Queue queue; … public decide(object value) { propose(value); Ball ball = this.queue.deq(); if (ball == Ball.RED) return proposed[i]; else return proposed[1-i]; } Other thread wins if I was second Art of Multiprocessor Programming

Why does this Work? If one thread gets the red ball Then the other gets the black ball Winner decides her own value Loser can find winner’s value in array Because threads write array Before dequeueing from queue Art of Multiprocessor Programming

Theorem We can solve 2-thread consensus using only A two-dequeuer queue, and Some atomic registers Art of Multiprocessor Programming

Implications contradiction Given Assume there exists A consensus protocol from queue and registers Assume there exists A queue implementation from atomic registers Substitution yields: A wait-free consensus protocol from atomic registers contradiction (1) Art of Multiprocessor Programming (1)

Corollary It is impossible to implement a two-dequeuer wait-free FIFO queue from read/write memory. Art of Multiprocessor Programming

Consensus Numbers An object X has consensus number n If it can be used to solve n-thread consensus Take any number of instances of X together with atomic read/write registers and implement n-thread consensus But not (n+1)-thread consensus Art of Multiprocessor Programming

Consensus Numbers Theorem Atomic read/write registers have consensus number 1 Multi-dequeuer FIFO queues have consensus number 2 Similar argument about other data types such as sets, stacks, double-ended queues, priority queues. Art of Multiprocessor Programming

Consensus Numbers Measure Synchronization Power Theorem If you can implement X from Y And X has consensus number c Then Y has consensus number at least c Art of Multiprocessor Programming

Multiple Assignment Theorem Atomic registers cannot implement multiple assignment (1) Art of Multiprocessor Programming (1)

Proof Strategy If we can write to 2/3 array elements Therefore We can solve 2-consensus Impossible with atomic registers Therefore Cannot implement multiple assignment with atomic registers Art of Multiprocessor Programming (1)

Proof Strategy Take a 3-element array A writes atomically to slots 0 and 1 B writes atomically to slots 1 and 2 Any thread can scan any set of locations Art of Multiprocessor Programming (1)

Double Assignment Interface interface Assign2 { public void assign(int i1, int v1, int i2, int v2); public int read(int i); } (4) Art of Multiprocessor Programming (4)

Double Assignment Interface interface Assign2 { public void assign(int i1, int v1, int i2, int v2); public int read(int i); } Atomically assign value[i1]= v1 value[i2]= v2 (4) Art of Multiprocessor Programming (4)

Double Assignment Interface interface Assign2 { public void assign(int i1, int v1, int i2, int v2); public int read(int i); } Return i-th value (4) Art of Multiprocessor Programming (4)

Initially A B Writes to 0 and 1 Writes to 1 and 2 Art of Multiprocessor Programming

Thread A wins if A Thread B didn’t move B Art of Multiprocessor Programming (1)

Thread A wins if A Thread B moved later B Art of Multiprocessor Programming (1)

Thread A loses if A Thread B moved earlier B Art of Multiprocessor Programming (1)

Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(Object value) { propose(value); int i = ThreadID.get(), j = 1 – i; a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} (4) Art of Multiprocessor Programming (4)

Extends ConsensusProtocol Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { propose(value); int i = ThreadID.get(), j = 1 – i; a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} To save space and make the code clearer we wrote that it extends consensus while it actually extends ConsensusProtocol and omitted that Decide sets j=i-1 and then proposes value. Assume this appears in all the code. Extends ConsensusProtocol (4) Art of Multiprocessor Programming (4)

Three slots initialized to EMPTY Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { propose(value); int i = ThreadID.get(), j = 1 – i; a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} Three slots initialized to EMPTY (4) Art of Multiprocessor Programming (4)

Assign id 0 to entries 0,1 (or id 1 to entries 1,2) Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { propose(value); int i = ThreadID.get(), j = 1 – i; a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} Assign id 0 to entries 0,1 (or id 1 to entries 1,2) (4) Art of Multiprocessor Programming (4)

Read the register my thread didn’t assign Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { propose(value); int i = ThreadID.get(), j = 1 – i; a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} Read the register my thread didn’t assign (4) Art of Multiprocessor Programming (4)

Other thread didn’t move, so I win Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} Other thread didn’t move, so I win (4) Art of Multiprocessor Programming (4)

Other thread moved later so I win Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} Other thread moved later so I win (4) Art of Multiprocessor Programming (4)

Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} OK, I win. (4) Art of Multiprocessor Programming (4)

Other thread moved first, so I lose Multi-Consensus Code class MultiConsensus extends …{ Assign2 a = new Assign2(3, EMPTY); public Object decide(object value) { a.assign(i, i, i+1, i); int other = a.read((i+2) % 3); if (other==EMPTY||other==a.read(1)) return proposed[i]; else return proposed[j]; }} (1) Other thread moved first, so I lose (4) Art of Multiprocessor Programming (4)

Summary If a thread can assign atomically to 2 out of 3 array locations Then we can solve 2-consensus Therefore No wait-free multi-assignment From read/write registers Art of Multiprocessor Programming

Read-Modify-Write Objects Method call Returns object’s prior value x Replaces x with mumble(x) Art of Multiprocessor Programming

Read-Modify-Write public abstract class RMWRegister { private int value; public int synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } (1) Art of Multiprocessor Programming

Read-Modify-Write Return prior value public abstract class RMWRegister { private int value; public int synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Return prior value (1) Art of Multiprocessor Programming

Apply function to current value Read-Modify-Write public abstract class RMWRegister { private int value; public int synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Apply function to current value (1) Art of Multiprocessor Programming

RMW Everywhere! Most synchronization instructions The rest are RMW methods The rest Can be trivially transformed into RMW methods Art of Multiprocessor Programming

Example: Read public abstract class RMWRegister { private int value; public int synchronized read() { int prior = this.value; this.value = this.value; return prior; } (1) Art of Multiprocessor Programming

Apply f(v)=v, the identity function Example: Read public abstract class RMW { private int value; public int synchronized read() { int prior = this.value; this.value = this.value; return prior; } Apply f(v)=v, the identity function (1) Art of Multiprocessor Programming

Example: getAndSet public abstract class RMWRegister { private int value; public int synchronized getAndSet(int v) { int prior = this.value; this.value = v; return prior; } … (1) Art of Multiprocessor Programming

Example: getAndSet (swap) public abstract class RMWRegister { private int value; public int synchronized getAndSet(int v) { int prior = this.value; this.value = v; return prior; } … F(x)=v is constant function (1) Art of Multiprocessor Programming

getAndIncrement public abstract class RMWRegister { private int value; public int synchronized getAndIncrement() { int prior = this.value; this.value = this.value + 1; return prior; } … (1) Art of Multiprocessor Programming

getAndIncrement F(x) = x+1 public abstract class RMWRegister { private int value; public int synchronized getAndIncrement() { int prior = this.value; this.value = this.value + 1; return prior; } … F(x) = x+1 (1) Art of Multiprocessor Programming

getAndAdd public abstract class RMWRegister { private int value; public int synchronized getAndAdd(int a) { int prior = this.value; this.value = this.value + a; return prior; } … (1) Art of Multiprocessor Programming

Example: getAndAdd F(x) = x+a public abstract class RMWRegister { private int value; public int synchronized getAndIncrement(int a) { int prior = this.value; this.value = this.value + a; return prior; } … F(x) = x+a (1) Art of Multiprocessor Programming

compareAndSet public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } (1) Art of Multiprocessor Programming

If value is what was expected, … compareAndSet public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } If value is what was expected, … (1) Art of Multiprocessor Programming

compareAndSet … replace it public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } … replace it (1) Art of Multiprocessor Programming

compareAndSet Report success public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } Report success (1) Art of Multiprocessor Programming

Otherwise report failure compareAndSet public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } Otherwise report failure (1) Art of Multiprocessor Programming

Lets characterize F(x)… Read-Modify-Write public abstract class RMWRegister { private int value; public void synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Lets characterize F(x)… (1) Art of Multiprocessor Programming

Definition A RMW method With function mumble(x) is non-trivial if there exists a value v Such that v ≠ mumble(v) Art of Multiprocessor Programming

Par Example Identity(x) = x getAndIncrement(x) = x+1 is trivial is non-trivial Art of Multiprocessor Programming

Theorem Any non-trivial RMW object has consensus number at least 2 No wait-free implementation of RMW registers from atomic registers Hardware RMW instructions not just a convenience Art of Multiprocessor Programming

Reminder Subclasses of consensus have propose(x) method which just stores x into proposed[i] built-in method decide(object value) method which determines winning value customized, class-specific method Art of Multiprocessor Programming

Proof public class RMWConsensus extends ConsensusProtocol { private RMWRegister r = v; public Object decide(object value) { propose(value); if (r.getAndMumble() == v) return proposed[i]; else return proposed[j]; }} (4) Art of Multiprocessor Programming

Proof Initialized to v public class RMWConsensus extends ConsensusProtocol { private RMWRegister r = v; public Object decide(object value) { propose(value); if (r.getAndMumble() == v) return proposed[i]; else return proposed[j]; }} Initialized to v (4) Art of Multiprocessor Programming

Proof Am I first? public class RMWConsensus extends Consensus { private RMWRegister r = v; public Object decide(object value) { if (r.getAndMumble() == v) return proposed[i]; else return proposed[j]; }} Am I first? (4) Art of Multiprocessor Programming

Proof Yes, return my input public class RMWConsensus extends ConsensusProtocol { private RMWRegister r = v; public Object decide(object value) { propose(value); if (r.getAndMumble() == v) return proposed[i]; else return proposed[j]; }} Yes, return my input (4) Art of Multiprocessor Programming

No, return other’s input Proof public class RMWConsensus extends ConsensusProtocol { private RMWRegister r = v; public Object decide(object value) { propose(value); if (r.getAndMumble() == v) return proposed[i]; else return proposed[j]; }} No, return other’s input (4) Art of Multiprocessor Programming

Proof We have displayed A two-thread consensus protocol Using any non-trivial RMW object Art of Multiprocessor Programming

Interfering RMW Let F be a set of functions such that for all fi and fj, either Commute: fi(fj(v))=fj(fi(v)) Overwrite: fi(fj(v))=fi(v) Claim: Any set of RMW objects that commutes or overwrites has consensus number exactly 2 Art of Multiprocessor Programming

Examples “test-and-set” getAndSet(1) f(v)=1 “swap” getAndSet(x) f(v,x)=x “fetch-and-inc” getAndIncrement() f(v)=v+1 Overwrite fi(fj(v))=fi(v) Overwrite fi(fj(v))=fi(v) Commute fi(fj(v))= fj(fi(v)) Art of Multiprocessor Programming

Meanwhile Back at the Critical State A about to apply fA B about to apply fB c 0-valent 1-valent Art of Multiprocessor Programming

Maybe the Functions Commute A applies fA B applies fB B applies fB A applies fA C runs solo C runs solo 1 0-valent 1-valent Art of Multiprocessor Programming

Maybe the Functions Commute A applies fA B applies fB These states look the same to C B applies fB A applies fA Contradiction C runs solo C runs solo 1 0-valent 1-valent Art of Multiprocessor Programming

Maybe the Functions Overwrite A applies fA B applies fB A applies fA C runs solo C runs solo 1 0-valent 1-valent Art of Multiprocessor Programming

Maybe the Functions Overwrite These states look the same to C c A applies fA B applies fB A applies fA C runs solo Contradiction C runs solo 1 0-valent 1-valent Art of Multiprocessor Programming

Impact Many early machines provided these “weak” RMW instructions Test-and-set (IBM 360) Fetch-and-add (NYU Ultracomputer) Swap (Original SPARCs) We now understand their limitations But why do we want consensus anyway? Art of Multiprocessor Programming

compareAndSet public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } (1) Art of Multiprocessor Programming

replace value if its what we expected, … compareAndSet public abstract class RMWRegister { private int value; public boolean synchronized compareAndSet(int expected, int update) { int prior = this.value; if (this.value==expected) { this.value = update; return true; } return false; } … } replace value if its what we expected, … (1) Art of Multiprocessor Programming

compareAndSet Has ∞ Consensus Number public class RMWConsensus extends ConsensusProtocol { private AtomicInteger r = new AtomicInteger(-1); public Object decide(object value) { propose(value); r.compareAndSet(-1,i); return proposed[r.get()]; } (4) Art of Multiprocessor Programming

compareAndSet Has ∞ Consensus Number public class RMWConsensus extends ConsensusProtocol { private AtomicInteger r = new AtomicInteger(-1); public Object decide(object value) { propose(value) r.compareAndSet(-1,i); return proposed[r.get()]; } Initialized to -1 (4) Art of Multiprocessor Programming

compareAndSet Has ∞ Consensus Number public class RMWConsensus extends ConsensusProtocol { private AtomicInteger r = new AtomicInteger(-1); public Object decide(object value) { propose(value); r.compareAndSet(-1,i); return proposed[r.get()]; } Try to swap in my id (4) Art of Multiprocessor Programming

compareAndSet Has ∞ Consensus Number public class RMWConsensus extends ConsensusProtocol { private AtomicInteger r = new AtomicInteger(-1); public Object decide(object value) { propose(value); r.compareAndSet(-1,i); return proposed[r.get()]; } Decide winner’s preference (4) Art of Multiprocessor Programming

The Consensus Hierarchy 1 Read/Write Registers, Snapshots… 2 getAndSet, getAndIncrement, … . ∞ compareAndSet,… Art of Multiprocessor Programming

Multiple Assignment Atomic k-assignment Solves consensus for 2k-2 threads Every even consensus number has an object (can be extended to odd numbers) Art of Multiprocessor Programming

Lock-Freedom Lock-free: in an infinite execution infinitely often some method call finishes (obviously, in a finite number of steps) Pragmatic approach Implies no mutual exclusion NOTE: Lock-free is the same as wait-free if the execution is finite. “Lock-free is to wait-free as deadlock-free is to lockout-free.” In other words, Lock-free and Deadlock-free are “stalinistic”, preferring group progress, while Wait-free and Lockout-free guarantee individual progress. Any wait-free implementation is lock-free. Art of Multiprocessor Programming

Lock-Free vs. Wait-free Wait-Free: each method call takes a finite number of steps to finish Lock-free: infinitely often some method call finishes NOTE: Lock-free is the same as wait-free if the execution is finite. “Lock-free is to wait-free as deadlock-free is to lockout-free.” In other words, Lock-free and Deadlock-free are “stalinistic”, preferring group progress, while Wait-free and Lockout-free guarantee individual progress. Any wait-free implementation is lock-free. Art of Multiprocessor Programming

Lock-Freedom Any wait-free implementation is lock-free. Lock-free is the same as wait- free if the execution is finite. Old saying: “Lock-free is to wait-free as deadlock-free is to lockout-free.” NOTE: Lock-free is the same as wait-free if the execution is finite. “Lock-free is to wait-free as deadlock-free is to lockout-free.” In other words, Lock-free and Deadlock-free are “stalinistic”, preferring group progress, while Wait-free and Lockout-free guarantee individual progress. Any wait-free implementation is lock-free. Art of Multiprocessor Programming

Lock-Free Implementations Lock-free consensus is as impossible as wait-free consensus All the results we presented hold for lock-free algorithms also. (2) Art of Multiprocessor Programming

There is More: Universality Consensus is universal From n-thread consensus Wait-free/Lock-free Linearizable n-threaded Implementation Of any sequentially specified object Stay tuned… Art of Multiprocessor Programming

Art of Multiprocessor Programming           This work is licensed under a Creative Commons Attribution-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. Art of Multiprocessor Programming