Presentation is loading. Please wait.

Presentation is loading. Please wait.

Foundations of Shared Memory Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS.

Similar presentations


Presentation on theme: "Foundations of Shared Memory Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS."— Presentation transcript:

1 Foundations of Shared Memory Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS 640 University of Pennsylvania

2 © 2007 Herlihy & Shavit2 Fundamentals What is the weakest form of communication that supports mutual exclusion? What is the weakest shared object that allows shared-memory computation?

3 © 2007 Herlihy & Shavit3 Alan Turing Helped us understand what is and is not computable on a sequential machine. Still best model available

4 © 2007 Herlihy & Shavit4 011010 1 Turing Machine Reads and Writes Infinite tape Finite State Controller

5 © 2007 Herlihy & Shavit5 Turing Computability Mathematical model of computation What is (and is not) computable Efficiency (mostly) irrelevant 011010 1

6 © 2007 Herlihy & Shavit6 Shared-Memory Computability? Mathematical model of concurrent computation What is (and is not) concurrently computable Efficiency (mostly) irrelevant 10011 Shared Memory

7 © 2007 Herlihy & Shavit7 Foundations of Shared Memory To understand modern multiprocessors we need to ask some basic questions …

8 © 2007 Herlihy & Shavit8 Foundations of Shared Memory To understand modern multiprocessors we need to ask some basic questions … What is the weakest useful form of shared memory?

9 © 2007 Herlihy & Shavit9 Foundations of Shared Memory To understand modern multiprocessors we need to ask some basic questions … What is the weakest useful form of shared memory? What can it do?

10 © 2007 Herlihy & Shavit10 Foundations of Shared Memory To understand modern multiprocessors we need to ask some basic questions … What is the weakest useful form of shared memory? What can it do? What can’t it do?

11 © 2007 Herlihy & Shavit11 Register 10011 Holds a (binary) value * * A memory location: name is historical

12 © 2007 Herlihy & Shavit12 Register Can be read 10011

13 © 2007 Herlihy & Shavit13 Register Can be written 10011 01100

14 © 2007 Herlihy & Shavit14 public interface Register { public T read(); public void write(T v); } Registers

15 © 2007 Herlihy & Shavit15 public interface Register { public T read(); public void write(T v); } Registers Type of register (usually Boolean or m-bit Integer)

16 © 2007 Herlihy & Shavit16 10011 Single-Reader/Single-Writer Register 01100 10011

17 © 2007 Herlihy & Shavit17 10011 Multi-Reader/Single-Writer Register 01100 10011

18 © 2007 Herlihy & Shavit18 mumble 11011 Multi-Reader/Multi-Writer Register mumble 10011 01010

19 © 2007 Herlihy & Shavit19 Jargon Watch SRSW –Single-reader single-writer MRSW –Multi-reader single-writer MRMW –Multi-reader multi-writer

20 © 2007 Herlihy & Shavit20 Safe Register write(1001) read(1001) OK if reads and writes don’t overlap (2)

21 © 2007 Herlihy & Shavit21 Safe Register write(1001) Some valid value if reads and writes do overlap read(????) 0000 1001 1111 $*&v

22 © 2007 Herlihy & Shavit22 Regular Register write(0) read(1) write(1) read(0) Single Writer Readers return: –Old value if no overlap (safe) –Old or one of new values if overlap

23 © 2007 Herlihy & Shavit23 Regular or Not? write(0) read(1) write(1) read(0)

24 © 2007 Herlihy & Shavit24 Regular or Not? write(0) read(1) write(1) read(0) Overlap: returns new value

25 © 2007 Herlihy & Shavit25 Regular or Not? write(0)write(1) read(0) Overlap: returns old value

26 © 2007 Herlihy & Shavit26 Regular or Not? write(0) read(1) write(1) read(0) regular

27 © 2007 Herlihy & Shavit27 Regular ≠ Linearizable write(0) read(1) write(1) read(0) write(1) already happened explain this!

28 © 2007 Herlihy & Shavit28 Atomic Register write(1001) read(1001) Linearizable to sequential safe register write(1010) read(1010)

29 © 2007 Herlihy & Shavit29 Atomic Register write(1001) read(1001) write(1010) read(1010)

30 © 2007 Herlihy & Shavit30 Register Space MRMW MRSW SRSW Safe Regular Atomic M-valued Boolean

31 © 2007 Herlihy & Shavit31 Weakest Register 1 0 1 1 Single readerSingle writer Safe Boolean register

32 © 2007 Herlihy & Shavit32 Weakest Register Single readerSingle writer Get correct reading if not during state transition flipflop 010 010

33 © 2007 Herlihy & Shavit33 Results From SRSW safe Boolean register –All the other registers –Mutual exclusion But not everything! –Consensus hierarchy (2)

34 © 2007 Herlihy & Shavit34 Locking within Registers Not interesting to rely on mutual exclusion in register constructions We want registers to implement mutual exclusion! No fun to use mutual exclusion to implement itself!

35 © 2007 Herlihy & Shavit35 Wait-Free Implementations Definition: An object implementation is wait-free if every thread completes a method in a finite number of steps No mutual exclusion –Thread could halt in critical section –Build mutual exclusion from registers

36 © 2007 Herlihy & Shavit36 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot

37 © 2007 Herlihy & Shavit37 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Next

38 © 2007 Herlihy & Shavit38 public class SafeBoolMRSWRegister implements Register { public boolean read() { … } public void write(boolean x) { … } } (3) Register Names

39 © 2007 Herlihy & Shavit39 public class SafeBoolMRSWRegister implements Register { public boolean read() { … } public void write(boolean x) { … } } (3) Register Names property

40 © 2007 Herlihy & Shavit40 public class SafeBoolMRSWRegister implements Register { public boolean read() { … } public void write(boolean x) { … } } (3) Register Names property Size matters

41 © 2007 Herlihy & Shavit41 public class SafeBoolMRSWRegister implements Register { public boolean read() { … } public void write(boolean x) { … } } (3) Register Names property type How many readers & writers?

42 © 2007 Herlihy & Shavit42 Safe Boolean MRSW from Safe Boolean SRSW public class SafeBoolMRSWRegister implements Register { private SafeBoolSRSWRegister[] r = new SafeBoolSRSWRegister[N]; public void write(boolean x) { for (int j = 0; j < N; j++) r[j].write(x); } public boolean read() { int i = ThreadID.get(); return r[i].read(); }} (2)

43 © 2007 Herlihy & Shavit43 Safe Boolean MRSW from Safe Boolean SRSW public class SafeBoolMRSWRegister implements BooleanRegister { private SafeBoolSRSWRegister[] r = new SafeBoolSRSWRegister[N]; public void write(boolean x) { for (int j = 0; j < N; j++) r[j].write(x); } public boolean read() { int i = ThreadID.get(); return r[i].read(); }} (2) Each thread has own safe SRSW register

44 © 2007 Herlihy & Shavit44 Safe Boolean MRSW from Safe Boolean SRSW public class SafeBoolMRSWRegister implements BooleanRegister { private SafeBoolSRSWRegister[] r = new SafeBoolSRSWRegister[N]; public void write(boolean x) { for (int j = 0; j < N; j++) r[j].write(x); } public boolean read() { int i = ThreadID.get(); return r[i].read(); }} (2) write method

45 © 2007 Herlihy & Shavit45 Safe Boolean MRSW from Safe Boolean SRSW public class SafeBoolMRSWRegister implements BooleanRegister { private SafeBoolSRSWRegister[] r = new SafeBoolSRSWRegister[N]; public void write(boolean x) { for (int j = 0; j < N; j++) r[j].write(x); } public boolean read() { int i = ThreadID.get(); return r[i].read(); }} (2) Write each thread’s register one at a time

46 © 2007 Herlihy & Shavit46 Safe Boolean MRSW from Safe Boolean SRSW public class SafeBoolMRSWRegister implements BooleanRegister { private SafeBoolSRSWRegister[] r = new SafeBoolSRSWRegister[N]; public void write(boolean x) { for (int j = 0; j < N; j++) r[j].write(x); } public boolean read() { int i = ThreadID.get(); return r[i].read(); }} (2) read method

47 © 2007 Herlihy & Shavit47 Safe Boolean MRSW from Safe Boolean SRSW public class SafeBoolMRSWRegister implements BooleanRegister { private SafeBoolSRSWRegister[] r = new SafeBoolSRSWRegister[N]; public void write(boolean x) { for (int j = 0; j < N; j++) r[j].write(x); } public boolean read() { int i = ThreadID.get(); return r[i].read(); }} (2) Read my own register

48 © 2007 Herlihy & Shavit48 Safe Boolean MRSW from Safe Boolean SRSW 1 1 1 1 1 1 0 or 1 0 0 0 0 0 0 0 0 1 1

49 © 2007 Herlihy & Shavit49 1000 Q: Safe Multi-Valued MRSW Safe Multi-Valued SRSW? 1 1011 1 Any value in range 0 0 Yes, it works! 1011

50 © 2007 Herlihy & Shavit50 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Questions?

51 © 2007 Herlihy & Shavit51 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Next

52 © 2007 Herlihy & Shavit52 Regular Boolean MRSW from Safe Boolean MRSW 1 1 0 0 0 0 Regular: if it changed, OK to read 0 or 1 Safe register can return 0 or 1 even if the same value is written Regular: But only old value if not changed

53 © 2007 Herlihy & Shavit53 Regular Boolean MRSW from Safe Boolean MRSW public class RegBoolMRSWRegister implements Register { private boolean old; private SafeBoolMRSWRegister value; public void write(boolean x) { if (old != x) { value.write(x); old = x; }} public boolean read() { return value.read(); }} (2)

54 © 2007 Herlihy & Shavit54 Regular Boolean MRSW from Safe Boolean MRSW public class RegBoolMRSWRegister implements Register { threadLocal boolean old; private SafeBoolMRSWRegister value; public void write(boolean x) { if (old != x) { value.write(x); old = x; }} public boolean read() { return value.read(); }} (2) Last bit this thread wrote (OK, we’re cheating here on Java syntax)

55 © 2007 Herlihy & Shavit55 Regular Boolean MRSW from Safe Boolean MRSW public class RegBoolMRSWRegister implements Register { threadLocal boolean old; private SafeBoolMRSWRegister value; public void write(boolean x) { if (old != x) { value.write(x); old = x; }} public boolean read() { return value.read(); }} (2) Actual value

56 © 2007 Herlihy & Shavit56 Regular Boolean MRSW from Safe Boolean MRSW public class RegBoolMRSWRegister implements Register { threadLocal boolean old; private SafeBoolMRSWRegister value; public void write(boolean x) { if (old != x) { value.write(x); old = x; }} public boolean read() { return value.read(); }} (2) Is new value different from last value I wrote?

57 © 2007 Herlihy & Shavit57 Regular Boolean MRSW from Safe Boolean MRSW public class RegBoolMRSWRegister implements Register { threadLocal boolean old; private SafeBoolMRSWRegister value; public void write(boolean x) { if (old != x) { value.write(x); old = x; }} public boolean read() { return value.read(); }} (2) If so, change it (otherwise don’t!)

58 © 2007 Herlihy & Shavit58 Regular Boolean MRSW from Safe Boolean MRSW public class RegBoolMRSWRegister implements Register { threadLocal boolean old; private SafeBoolMRSWRegister value; public void write(boolean x) { if (old != x) { value.write(x); old = x; }} public boolean read() { return value.read(); }} (2) Overlap? No Overlap? No problem either Boolean value works

59 © 2007 Herlihy & Shavit59 Regular Multi-Valued MRSW to Safe Multi-Valued MRSW? 1 1 0101 Multi- valued Regular register can return only old or new when value changes! Safe register can return value in range other than old or new when value changes No, it does not work!

60 © 2007 Herlihy & Shavit60 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Questions?

61 © 2007 Herlihy & Shavit61 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Next

62 © 2007 Herlihy & Shavit62 MRSW Regular M-valued from MRSW Regular Boolean public class RegMRSWRegister implements Register{ RegBoolMRSWRegister[M] bit; public void write(int x) { this.bit[x].write(true); for (int i=x-1; i>=0; i--) this.bit[i].write(false); } public int read() { for (int i=0; i < M; i++) if (this.bit[i].read()) return i; }}

63 © 2007 Herlihy & Shavit63 MRSW Regular M-valued from MRSW Regular Boolean public class RegMRSWRegister implements Register{ RegBoolMRSWRegister[M] bit; public void write(int x) { this.bit[x].write(true); for (int i=x-1; i>=0; i--) this.bit[i].write(false); } public int read() { for (int i=0; i < M; i++) if (this.bit[i].read()) return i; }} Unary representation: bit[i] means value i

64 © 2007 Herlihy & Shavit64 MRSW Regular M-valued from MRSW Regular Boolean public class RegMRSWRegisterimplements Register { RegBoolMRSWRegister[m] bit; public void write(int x) { this.bit[x].write(true); for (int i=x-1; i>=0; i--) this.bit[i].write(false); } public int read() { for (int i=0; i < M; i++) if (this.bit[i].read()) return i; }} (1) Set bit x

65 © 2007 Herlihy & Shavit65 MRSW Regular M-valued from MRSW Regular Boolean public class RegMRSWRegisterimplements Register { RegBoolMRSWRegister[m] bit; public void write(int x) { this.bit[x].write(true); for (int i=x-1; i>=0; i--) this.bit[i].write(false); } public int read() { for (int i=0; i < M; i++) if (this.bit[i].read()) return i; }} (1) Clear bits from higher to lower

66 © 2007 Herlihy & Shavit66 MRSW Regular M-valued from MRSW Regular Boolean public class RegMRSWRegisterimplements Register { RegBoolMRSWRegister[m] bit; public void write(int x) { this.bit[x].write(true); for (int i=x-1; i>=0; i--) this.bit[i].write(false); } public int read() { for (int i=0; i < M; i++) if (this.bit[i].read()) return i; }} (1) Scan from lower to higher & return first bit set

67 © 2007 Herlihy & Shavit67 Writing M-Valued 0 1 2 3 4 5 6 7 110000 Write 5 Initially 0

68 © 2007 Herlihy & Shavit68 Writing M-Valued 0 1 2 3 4 5 6 7 110000 Write 5 5 0

69 © 2007 Herlihy & Shavit69 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot

70 © 2007 Herlihy & Shavit70 Road Map (Slight Detour) SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot SRSW Atomic

71 © 2007 Herlihy & Shavit71 SRSW Atomic From SRSW Regular 1234 Regular writer Regular reader 1234 5678 Instead of 5678… When is this a problem?

72 © 2007 Herlihy & Shavit72 SRSW Atomic From SRSW Regular 1234 Regular writer Regular reader 5678 time Reg write(5678) Reg read(5678) Initially 1234 Same as Atomic

73 © 2007 Herlihy & Shavit73 SRSW Atomic From SRSW Regular 1234 Regular writer Regular reader 1234 5678 Instead of 5678… time Reg write(5678) Reg read(1234) Initially 1234 Same as Atomic

74 © 2007 Herlihy & Shavit74 SRSW Atomic From SRSW Regular 1234 Regular writer Regular reader 1234 5678 Instead of 5678… time Reg write(5678) Reg read(1234) Initially 1234 Reg read(5678) not Atomic! Write 5678 happened

75 © 2007 Herlihy & Shavit75 Timestamped Values Writer writes value and stamp together Reader saves last reads (value,stamp) and returns new value only if higher stamp 1234 1:45 5678 2:00 5678 2:00

76 © 2007 Herlihy & Shavit76 SRSW Atomic From SRSW Regular writer reader 1:45 1234 Less than 2:00 5678 So stick with 5678 time Reg write(2:00 5678) read(1:45 1234) 1:45 1234 read(2:00 5678) 1234 1:45 5678 old = 2:00 > 5678 2:00 Same as Atomic

77 © 2007 Herlihy & Shavit77 Atomic Single Reader to Atomic Multi-Reader 1:451234 1:451234 1:4512341:451234 stampvalue One per reader

78 © 2007 Herlihy & Shavit78 Another Scenario 1:451234 2:005678 1:4512341:451234 stampvalue Writer starts write…

79 © 2007 Herlihy & Shavit79 Another Scenario 1:451234 2:005678 1:4512341:451234 stampvalue reader reads 2:00, 5678 zzz… 1:45 1234 later reader Yellow was completely after blue but read earlier value…not linearizable!

80 © 2007 Herlihy & Shavit80 Multi-Reader Redux 1:4512341:4512341:4512341:4512341:4512341:451234 One per thread 1:4512341:4512341:451234 123 1 2 3

81 © 2007 Herlihy & Shavit81 Multi-Reader Redux 1:4512341:4512341:4512341:4512341:4512341:4512341:4512341:451234 Writer writes column… 2:0056782:0056782:0056781:451234 reader reads row 2:00, 5678 1 123 1 2 3 2

82 © 2007 Herlihy & Shavit82 Multi-Reader Redux 1:4512341:4512341:4512341:4512341:4512341:4512341:4512341:4512342:0056781:451234 reader writes column to notify others of what it read 1 123 1 2 3 2 2:0056782:0056782:0056782:005678 zzz…after second write 2:00, 5678 Yellow reader will read new value in column written by earlier Blue reader

83 © 2007 Herlihy & Shavit83 Can’t Yellow Miss Blue’s Update? … Only if Readers Overlap… time write(2:00 5678) read(1:45 1234) 1:45 1234 read(2:00 5678) In which case its OK to read 1234

84 © 2007 Herlihy & Shavit84 Bad Case Only When Readers Don’t Overlap time write(2:00 5678) read(2:00 5678) 1:45 1234 read(2:00 5678) In which case Blue will complete writing 2:00 5678 to its column

85 © 2007 Herlihy & Shavit85 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Next

86 © 2007 Herlihy & Shavit86 Multi-Writer Atomic From Multi-Reader Atomic 1:451234 1:451234 1:4512341:451234 stampvalue Readers read all and take max (Lexicographic like Bakery) Each writer reads all then writes Max+1 to its register 2:005678 2:15XYZW Max is 2:15, return XYZW

87 © 2007 Herlihy & Shavit87 Atomic Execution Means its Linearizable time write(1) time (4) Read(max= 2)write(4) write(2) write(3)Read(max = 3) Read (max = 1) write(2)Read(max = 4)

88 © 2007 Herlihy & Shavit88 Linearization Points time write(1) time (4) Read(max= 2)write(4) write(2) write(3)Read(max = 3) Read (max = 1) write(2)Read(max = 4)

89 © 2007 Herlihy & Shavit89 Linearization Points time write(1) time Look at Writes First (4) write(4) write(2) write(3) write(2)

90 © 2007 Herlihy & Shavit90 Linearization Points time write(1) time (4) write(4) write(2) write(3) write(2) Order writes by TimeStamp

91 © 2007 Herlihy & Shavit91 Linearization Points time write(1) time (4) write(4) write(2) write(3) write(2) Read(max= 2) Read(max = 3) Read (max = 1) Read(max = 4) Order reads by max stamp read

92 © 2007 Herlihy & Shavit92 Linearization Points time write(1) time (4) write(4) write(2) write(3) write(2) Read(max= 2) Read(max = 3) Read (max = 1) Read(max = 4) Order reads by max stamp read

93 © 2007 Herlihy & Shavit93 Linearization Points time write(1) time (4) write(4) write(2) write(3) write(2) Read(max= 2) Read(max = 3) Read (max = 1) Read(max = 4) The linearization point depends on the execution (not a line in the code)!

94 © 2007 Herlihy & Shavit94 Road Map SRSW safe Boolean MRSW safe Boolean MRSW regular Boolean MRSW regular MRSW atomic MRMW atomic Atomic snapshot Next

95 © 2007 Herlihy & Shavit95 Atomic Snapshot update scan

96 © 2007 Herlihy & Shavit96 Atomic Snapshot Array of SWMR atomic registers Take instantaneous snapshot of all Generalizes to MRMW registers …

97 © 2007 Herlihy & Shavit97 Snapshot Interface public interface Snapshot { public int update(int v); public int[] scan(); } (2)

98 © 2007 Herlihy & Shavit98 Snapshot Interface public interface Snapshot { public int update(int v); public int[] scan(); } Thread i writes v to its register (2)

99 © 2007 Herlihy & Shavit99 Snapshot Interface public interface Snapshot { public int update(int v); public int[] scan(); } Instantaneous snapshot of all theads’ registers (2)

100 © 2007 Herlihy & Shavit100 Atomic Snapshot Collect –Read values one at a time Problem –Incompatible concurrent collects –Result not linearizable

101 © 2007 Herlihy & Shavit101 Clean Collects Clean Collect –Collect during which nothing changed –Can we make it happen? –Can we detect it?

102 © 2007 Herlihy & Shavit102 Simple Snapshot Put increasing labels on each entry Collect twice If both agree, –We’re done Otherwise, –Try again 1 22 1 7 13 18 12 = Collect2 Collect1 1 22 1 7 13 18 12

103 © 2007 Herlihy & Shavit103 Simple Snapshot: Update public class SimpleSnapshot implements Snapshot { private AtomicMRSWRegister[] register; public void update(int value) { int i = Thread.myIndex(); LabeledValue oldValue = register[i].read(); LabeledValue newValue = new LabeledValue(oldValue.label+1, value); register[i].write(newValue); } (1)

104 © 2007 Herlihy & Shavit104 Simple Snapshot: Update public class SimpleSnapshot implements Snapshot { private AtomicMRSWRegister[] register; public void update(int value) { int i = Thread.myIndex(); LabeledValue oldValue = register[i].read(); LabeledValue newValue = new LabeledValue(oldValue.label+1, value); register[i].write(newValue); } (1) One single-writer register per thread

105 © 2007 Herlihy & Shavit105 Simple Snapshot: Update public class SimpleSnapshot implements Snapshot { private AtomicMRSWRegister[] register; public void update(int value) { int i = Thread.myIndex(); LabeledValue oldValue = register[i].read(); LabeledValue newValue = new LabeledValue(oldValue.label+1, value); register[i].write(newValue); } (1) Write each time with higher label

106 © 2007 Herlihy & Shavit106 Simple Snapshot: Collect private LabeledValue[] collect() { LabeledValue[] copy = new LabeledValue[n]; for (int j = 0; j < n; j++) copy[j] = this.register[j].read(); return copy; } (1)

107 © 2007 Herlihy & Shavit107 Simple Snapshot private LabeledValue[] collect() { LabeledValue[] copy = new LabeledValue[n]; for (int j = 0; j < n; j++) copy[j] = this.register[j].read(); return copy; } (1) Just read each register into array

108 © 2007 Herlihy & Shavit108 Simple Snapshot: Scan public int[] scan() { LabeledValue[] oldCopy, newCopy; oldCopy = collect(); collect: while (true) { newCopy = collect(); if (!equals(oldCopy, newCopy)) { oldCopy = newCopy; continue collect; }} return getValues(newCopy); }}} (1)

109 © 2007 Herlihy & Shavit109 Simple Snapshot: Scan public int[] scan() { LabeledValue[] oldCopy, newCopy; oldCopy = collect(); collect: while (true) { newCopy = collect(); if (!equals(oldCopy, newCopy)) { oldCopy = newCopy; continue collect; }} return getValues(newCopy); }}} (1) Collect once

110 © 2007 Herlihy & Shavit110 Simple Snapshot: Scan public int[] scan() { LabeledValue[] oldCopy, newCopy; oldCopy = collect(); collect: while (true) { newCopy = collect(); if (!equals(oldCopy, newCopy)) { oldCopy = newCopy; continue collect; }} return getValues(newCopy); }}} (1) Collect once Collect twice

111 © 2007 Herlihy & Shavit111 Simple Snapshot: Scan public int[] scan() { LabeledValue[] oldCopy, newCopy; oldCopy = collect(); collect: while (true) { newCopy = collect(); if (!equals(oldCopy, newCopy)) { oldCopy = newCopy; continue collect; }} return getValues(newCopy); }}} (1) Collect once Collect twice On mismatch, try again

112 © 2007 Herlihy & Shavit112 Simple Snapshot: Scan public int[] scan() { LabeledValue[] oldCopy, newCopy; oldCopy = collect(); collect: while (true) { newCopy = collect(); if (!equals(oldCopy, newCopy)) { oldCopy = newCopy; continue collect; }} return getValues(newCopy); }}} (1) Collect once Collect twice On match, return values

113 © 2007 Herlihy & Shavit113 Simple Snapshot Linearizable Update is wait-free –No unbounded loops But Scan can starve –If interrupted by concurrent update

114 © 2007 Herlihy & Shavit114 Wait-Free Snapshot Add a scan before every update Write resulting snapshot together with update value If scan is continuously interrupted by updates, scan can take the update’s snapshot

115 © 2007 Herlihy & Shavit115 Wait-free Snapshot If A’s scan observes that B moved twice, then B completed an update while A’s scan was in progress time Update B ≠ ≠ 26 24 12 Collect 26 24 12 Collect 26 24 12 Collect

116 © 2007 Herlihy & Shavit116 Wait-free Snapshot time ≠ ≠ 26 24 12 Collect 26 24 12 Collect 26 24 12 Collect Update A B

117 © 2007 Herlihy & Shavit117 Wait-free Snapshot time ≠ ≠ 26 24 12 Collect 26 24 12 Collect 26 24 12 Collect Update A B ScanWrite

118 © 2007 Herlihy & Shavit118 Wait-free Snapshot time ≠ ≠ 26 24 12 Collect 26 24 12 Collect 26 24 12 Collect Update A B ScanWrite A can steal result of B’s scan

119 © 2007 Herlihy & Shavit119 Once is not Enough time ≠ 26 24 12 Collect 26 24 12 Collect Update A B ScanWrite Can A steal result of B’s scan?

120 © 2007 Herlihy & Shavit120 Once is not Enough time ≠ 26 24 12 Collect 26 24 12 Collect A B ScanWrite No Update C

121 © 2007 Herlihy & Shavit121 Someone Must Move Twice time Update B ≠ ≠ 26 24 12 Collect 26 24 12 Collect 26 24 12 Collect Why are scans wait-free?

122 © 2007 Herlihy & Shavit122 Wait-Free Snapshot Label public class SnapValue { public int label; public int value; public int[] snap; } (2)

123 © 2007 Herlihy & Shavit123 Wait-Free Snapshot Label public class SnapValue { public int label; public int value; public int[] snap; } (2) Counter incremented with each snapshot

124 © 2007 Herlihy & Shavit124 Wait-Free Snapshot Label public class SnapValue { public int label; public int value; public int[] snap; } (2) Actual value

125 © 2007 Herlihy & Shavit125 Wait-Free Snapshot Label public class SnapValue { public int label; public int value; public int[] snap; } (2) most recent snapshot

126 © 2007 Herlihy & Shavit126 Wait-free Update public void update(int value) { int i = Thread.myIndex(); int[] snap = this.scan(); SnapValue oldValue = r[i].read(); SnapValue newValue = new SnapValue(oldValue.label+1, value, snap); r[i].write(newValue); } (2)

127 © 2007 Herlihy & Shavit127 Wait-free Scan public void update(int value) { int i = Thread.myIndex(); int[] snap = this.scan(); SnapValue oldValue = r[i].read(); SnapValue newValue = new SnapValue(oldValue.label+1, value, snap); r[i].write(newValue); } (2) Take scan

128 © 2007 Herlihy & Shavit128 Wait-free Scan public void update(int value) { int i = Thread.myIndex(); int[] snap = this.scan(); SnapValue oldValue = r[i].read(); SnapValue newValue = new SnapValue(oldValue.label+1, value, snap); r[i].write(newValue); } (2) Take scan Label value with scan

129 © 2007 Herlihy & Shavit129 Wait-free Scan public int[] scan() { SnapValue[] oldCopy, newCopy; boolean[] moved = new boolean[n]; oldCopy = collect(); collect: while (true) { newCopy = collect(); for (int j = 0; j < n; j++) { if (oldCopy[j].label != newCopy[j].label) { … }} return getValues(newCopy); }}} (2) Keep track of who moved

130 © 2007 Herlihy & Shavit130 Wait-free Scan public int[] scan() { SnapValue[] oldCopy, newCopy; boolean[] moved = new boolean[n]; oldCopy = collect(); collect: while (true) { newCopy = collect(); for (int j = 0; j < n; j++) { if (oldCopy[j].label != newCopy[j].label) { … }} return getValues(newCopy); }}} (2) Repeated double collect

131 © 2007 Herlihy & Shavit131 Wait-free Scan public int[] scan() { SnapValue[] oldCopy, newCopy; boolean[] moved = new boolean[n]; oldCopy = collect(); collect: while (true) { newCopy = collect(); for (int j = 0; j < n; j++) { if (oldCopy[j].label != newCopy[j].label) { … }} return getValues(newCopy); }}} (2) If mismatch detected…lets expand here…

132 © 2007 Herlihy & Shavit132 Mismatch Detected if (oldCopy[j].label != newCopy[j].label) { if (moved[j]) {// second move return oldCopy[j].snap; } else { moved[j] = true; oldCopy = newCopy; continue collect; }}} return getValues(newCopy); }}} (2)

133 © 2007 Herlihy & Shavit133 Mismatch Detected if (oldCopy[j].label != newCopy[j].label) { if (moved[j]) { return oldCopy[j].snap; } else { moved[j] = true; oldCopy = newCopy; continue collect; }}} return getValues(newCopy); }}} If thread moved twice, just steal its snapshot (2)

134 © 2007 Herlihy & Shavit134 Mismatch Detected if (oldCopy[j].label != newCopy[j].label) { if (moved[j]) {// second move return oldCopy[j].snap; } else { moved[j] = true; oldCopy = newCopy; continue collect; }}} return getValues(newCopy); }}} (2) Remember that thread moved

135 © 2007 Herlihy & Shavit135 Wait-free Scan public int[] scan() { SnapValue[] oldCopy, newCopy; boolean[] moved = new boolean[n]; oldCopy = collect(); collect: while (true) { newCopy = collect(); for (int j = 0; j < n; j++) { if (oldCopy[j].label != newCopy[j].label) { … }} return getValues(newCopy); }}} (2)

136 © 2007 Herlihy & Shavit136 Wait-free scan update So some thread must have had clean collect scan update scan At most n-1 depth

137 © 2007 Herlihy & Shavit137 Observations Uses unbounded counters –can be replaced with 2 bits Assumes SWMR registers –for labels –can be extended to MRMW

138 © 2007 Herlihy & Shavit138 Summary We saw we could implement MRMW multi valued snapshot objects From SRSW binary safe registers (simple flipflops) But what is the next step to attempt with read-write registers?

139 © 2007 Herlihy & Shavit139 Consensus: Each Thread has a Private Input 32 19 21

140 © 2007 Herlihy & Shavit140 They Communicate

141 © 2007 Herlihy & Shavit141 They Agree on One Thread’s Input 19

142 © 2007 Herlihy & Shavit142 Formally: Consensus Consistent: –all threads decide the same value Valid: –the common decision value is some thread's input

143 © 2007 Herlihy & Shavit143 No Wait-Free Implementation of Consensus using Registers ???

144 © 2007 Herlihy & Shavit144 Formally Theorem –There is no wait-free implementation of n-thread consensus from read-write registers Implication –Asynchronous computability different from Turing computability

145 © 2007 Herlihy & Shavit145 Proof Strategy Assume otherwise Reason about the properties of any such protocol Derive a contradiction Suffices to prove for binary consensus and n=2

146 © 2007 Herlihy & Shavit146 Wait-Free Computation Either A or B “moves” Moving means –Register read –Register write A movesB moves

147 © 2007 Herlihy & Shavit147 The Two-Move Tree Initial state Final states

148 © 2007 Herlihy & Shavit148 Decision Values 10 0111

149 © 2007 Herlihy & Shavit149 Bivalent: Both Possible 111 bivalent 10 0

150 © 2007 Herlihy & Shavit150 Univalent: Single Value Possible 111 univalent 10 0

151 © 2007 Herlihy & Shavit151 x-valent: x Only Possible Decision 0 111 1-valent 0 1

152 © 2007 Herlihy & Shavit152 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

153 © 2007 Herlihy & Shavit153 Claim Some initial state is bivalent Outcome depends on –Chance –Whim of the scheduler … Lets prove it …

154 © 2007 Herlihy & Shavit154 Both Inputs 0 Univalent: all executions must decide 0 0 0

155 © 2007 Herlihy & Shavit155 Both Inputs 0 Including this solo execution by A 0

156 © 2007 Herlihy & Shavit156 Both Inputs 1 All executions must decide 1 1 1

157 © 2007 Herlihy & Shavit157 Both Inputs 1 Including this solo execution by B 1

158 © 2007 Herlihy & Shavit158 What if inputs differ? 1 0 By Way of contradiction: If univalent all executions must decide on same value

159 © 2007 Herlihy & Shavit159 0-valent Critical States 1-valent critical

160 © 2007 Herlihy & Shavit160 From a Critical State c If A goes first, protocol decides 0 If B goes first, protocol decides 1 0-valent 1-valent

161 © 2007 Herlihy & Shavit161 Reaching Critical State CACA CACA CBCB c CBCB univalent 0-valent 1-valent initially bivalent

162 © 2007 Herlihy & Shavit162 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

163 © 2007 Herlihy & Shavit163 Model Dependency So far, memory-independent! True for –Registers –Message-passing –Carrier pigeons –Any kind of asynchronous computation

164 © 2007 Herlihy & Shavit164 Read-Write Memory Reads and/or writes To same/different registers

165 © 2007 Herlihy & Shavit165 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

166 © 2007 Herlihy & Shavit166 Possible Interactions x.read()y.read()x.write()y.write() x.read() ???? y.read() ???? x.write() ???? y.write() ???? A reads x A reads y

167 © 2007 Herlihy & Shavit167 Some Thread Reads A runs solo, eventually decides 0 B reads x 1 0 A runs solo, eventually decides 1 c States look the same to A Contradiction

168 © 2007 Herlihy & Shavit168 Possible Interactions x.read()y.read()x.write()y.write() x.read() no y.read() no x.write() no ?? y.write() no ??

169 © 2007 Herlihy & Shavit169 Writing Distinct Registers A writes yB writes x 10 c Same story A writes y B writes x Contradiction

170 © 2007 Herlihy & Shavit170 Possible Interactions x.read()y.read()x.write()y.write() x.read() no y.read() no x.write() no ? y.write() no ?

171 © 2007 Herlihy & Shavit171 Writing Same Registers States look the same to A A writes x B writes x 1 A runs solo, eventually decides 1 c 0 A runs solo, eventually decides 0 A writes x Contradiction

172 © 2007 Herlihy & Shavit172 That’s All, Folks! x.read()y.read()x.write()y.write() x.read() no y.read() no x.write() no y.write() no QED

173 © 2007 Herlihy & Shavit173 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

174 © 2007 Herlihy & Shavit174 What Does Consensus have to do with Concurrent Objects?

175 © 2007 Herlihy & Shavit175 Consensus Object public interface Consensus { Object decide(object value); }

176 © 2007 Herlihy & Shavit176 Concurrent Consensus Object We consider only one time objects: –each thread calls method only once Linearizable to consensus object: –Winner’s call went first

177 © 2007 Herlihy & Shavit177 Generic Consensus Protocol abstract class ConsensusProtocol implements Consensus { protected T[] proposed = new T[N]; protected void propose(T value) { proposed[ThreadID.get()] = value; } abstract public T decide(T value); }

178 © 2007 Herlihy & Shavit178 abstract class ConsensusProtocol implements Consensus { protected T[] proposed = new T[N]; protected void propose(T value) { proposed[ThreadID.get()] = value; } abstract public T decide(T value); } Generic Consensus Protocol Each thread’s proposed value

179 © 2007 Herlihy & Shavit179 abstract class ConsensusProtocol implements Consensus { protected T[] proposed = new T[N]; protected void propose(T value) { proposed[ThreadID.get()] = value; } abstract public T decide(T value); } Generic Consensus Protocol Propose a value

180 © 2007 Herlihy & Shavit180 abstract class ConsensusProtocol implements Consensus { protected T[] proposed = new T[N]; protected void propose(T value) { proposed[ThreadID.get()] = value; } abstract public T decide(T value); } Generic Consensus Protocol Decide a value: abstract method means subclass does the heavy lifting (real work)

181 © 2007 Herlihy & Shavit181 Can a FIFO Queue Implement Consensus?

182 © 2007 Herlihy & Shavit182 FIFO Consensus proposed array FIFO Queue with red and black balls 8 Coveted red ballDreaded black ball

183 © 2007 Herlihy & Shavit183 Protocol: Write Value to Array 01 0

184 © 2007 Herlihy & Shavit184 0 Protocol: Take Next Item from Queue 01 8

185 © 2007 Herlihy & Shavit185 01 Protocol: Take Next Item from Queue I got the coveted red ball, so I will decide my value I got the dreaded black ball, so I will decide the other’s value from the array 8

186 © 2007 Herlihy & Shavit186 public class QueueConsensus extends ConsensusProtocol { private Queue queue; public QueueConsensus() { queue = new Queue(); queue.enq(Ball.RED); queue.enq(Ball.BLACK); } … } Consensus Using FIFO Queue

187 © 2007 Herlihy & Shavit187 public class QueueConsensus extends ConsensusProtocol { private Queue queue; public QueueConsensus() { this.queue = new Queue(); this.queue.enq(Ball.RED); this.queue.enq(Ball.BLACK); } … } Initialize Queue 8

188 © 2007 Herlihy & Shavit188 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]; } Who Won?

189 © 2007 Herlihy & Shavit189 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]; } Who Won? Race to dequeue first queue item

190 © 2007 Herlihy & Shavit190 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]; } Who Won? i = ThreadID.get(); I win if I was first

191 © 2007 Herlihy & Shavit191 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]; } Who Won? Other thread wins if I was second

192 © 2007 Herlihy & Shavit192 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

193 © 2007 Herlihy & Shavit193 Theorem We can solve 2-thread consensus using only –A two-dequeuer queue, and –Some atomic registers

194 © 2007 Herlihy & Shavit194 Implications Given –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

195 © 2007 Herlihy & Shavit195 Corollary It is impossible to implement –a two-dequeuer wait-free FIFO queue –from read/write memory.

196 © 2007 Herlihy & Shavit196 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

197 © 2007 Herlihy & Shavit197 Consensus Numbers Theorem –Atomic read/write registers have consensus number 1 Theorem –Multi-dequeuer FIFO queues have consensus number at least 2

198 © 2007 Herlihy & Shavit198 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

199 © 2007 Herlihy & Shavit199 Synchronization Speed Limit Conversely –If X has consensus number c –And Y has consensus number d < c –Then there is no way to construct a wait-free implementation of X by Y This theorem will be very useful –Unforeseen practical implications!

200 © 2007 Herlihy & Shavit200 Challenge Problem Snapshot means –Write any array element –Read multiple array elements atomically What about –Write multiple array elements atomically –Scan any array elements Call this problem multiple assignment

201 © 2007 Herlihy & Shavit201 Multiple Assignment Theorem Atomic registers cannot implement multiple assignment Weird or what? –Single write/multi read OK –Multi write/multi read impossible

202 © 2007 Herlihy & Shavit202 Proof Strategy If we can write to 2/3 array elements –We can solve 2-consensus –Impossible with atomic registers Therefore –Cannot implement multiple assignment with atomic registers (1)

203 © 2007 Herlihy & Shavit203 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

204 © 2007 Herlihy & Shavit204 Double Assignment Interface interface Assign2 { public void assign(int i 1, int v 1, int i 2, int v 2 ); public int read(int i); }

205 © 2007 Herlihy & Shavit205 Double Assignment Interface interface Assign2 { public void assign(int i 1, int v 1, int i 2, int v 2 ); public int read(int i); } Atomically assign value[i 1 ]= v 1 value[i 2 ]= v 2

206 © 2007 Herlihy & Shavit206 Double Assignment Interface interface Assign2 { public void assign(int i 1, int v 1, int i 2, int v 2 ); public int read(int i); } Return i-th value

207 © 2007 Herlihy & Shavit207 Initially Writes to 0 and 1 Writes to 1 and 2 A B

208 © 2007 Herlihy & Shavit208 Thread A wins if A B Thread B didn’t move

209 © 2007 Herlihy & Shavit209 Thread A wins if A B Thread B moved later

210 © 2007 Herlihy & Shavit210 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]; }}

211 © 2007 Herlihy & Shavit211 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]; }} Three slots initialized to EMPTY

212 © 2007 Herlihy & Shavit212 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]; }} Assign id 0 to entries 0,1 (or id 1 to entries 1,2)

213 © 2007 Herlihy & Shavit213 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]; }} Read the register my thread didn’t assign

214 © 2007 Herlihy & Shavit214 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]; }} Multi-Consensus Code Other thread didn’t move, so I win

215 © 2007 Herlihy & Shavit215 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]; }} Multi-Consensus Code Other thread moved later so I win

216 © 2007 Herlihy & Shavit216 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.

217 © 2007 Herlihy & Shavit217 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]; }} Multi-Consensus Code (1) Other thread moved first, so I lose

218 © 2007 Herlihy & Shavit218 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

219 © 2007 Herlihy & Shavit219 Read-Modify-Write Objects Method call –Returns object’s prior value x –Replaces x with mumble(x)

220 © 2007 Herlihy & Shavit220 public abstract class RMWRegister { private int value; public int synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Read-Modify-Write

221 © 2007 Herlihy & Shavit221 public abstract class RMWRegister { private int value; public int synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Read-Modify-Write Return prior value

222 © 2007 Herlihy & Shavit222 public abstract class RMWRegister { private int value; public int synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Read-Modify-Write Apply function to current value

223 © 2007 Herlihy & Shavit223 RMW Everywhere! Most synchronization instructions –are RMW methods The rest –Can be trivially transformed into RMW methods

224 © 2007 Herlihy & Shavit224 public abstract class RMWRegister { private int value; public int synchronized read() { int prior = this.value; this.value = this.value; return prior; } Example: Read

225 © 2007 Herlihy & Shavit225 public abstract class RMW { private int value; public int synchronized read() { int prior = this.value; this.value = this.value; return prior; } Example: Read Apply f(v)=v, the identity function

226 © 2007 Herlihy & Shavit226 public abstract class RMWRegister { private int value; public int synchronized getAndSet(int v) { int prior = this.value; this.value = v; return prior; } … } Example: getAndSet

227 © 2007 Herlihy & Shavit227 public abstract class RMWRegister { private int value; public int synchronized getAndSet(int v) { int prior = this.value; this.value = v; return prior; } … } Example: getAndSet (swap) F(x)=v is constant function

228 © 2007 Herlihy & Shavit228 public abstract class RMWRegister { private int value; public int synchronized getAndIncrement() { int prior = this.value; this.value = this.value + 1; return prior; } … } getAndIncrement

229 © 2007 Herlihy & Shavit229 public abstract class RMWRegister { private int value; public int synchronized getAndIncrement() { int prior = this.value; this.value = this.value + 1; return prior; } … } getAndIncrement (1) F(x) = x+1

230 © 2007 Herlihy & Shavit230 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; } … } compareAndSet

231 © 2007 Herlihy & Shavit231 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; } … } compareAndSet If value is what was expected, …

232 © 2007 Herlihy & Shavit232 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; } … } compareAndSet … replace it

233 © 2007 Herlihy & Shavit233 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; } … } compareAndSet Report success

234 © 2007 Herlihy & Shavit234 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; } … } compareAndSet Otherwise report failure

235 © 2007 Herlihy & Shavit235 public abstract class RMWRegister { private int value; public void synchronized getAndMumble() { int prior = this.value; this.value = mumble(this.value); return prior; } Read-Modify-Write Lets characterize F(x)…

236 © 2007 Herlihy & Shavit236 Definition A RMW method –With function mumble(x) – is non-trivial if there exists a value v –Such that v ≠ mumble(v)

237 © 2007 Herlihy & Shavit237 Par Example Identity(x) = x – is trivial getAndIncrement(x) = x+1 –is non-trivial

238 © 2007 Herlihy & Shavit238 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

239 © 2007 Herlihy & Shavit239 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]; }}

240 © 2007 Herlihy & Shavit240 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]; }} Proof Initialized to v

241 © 2007 Herlihy & Shavit241 Proof 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?

242 © 2007 Herlihy & Shavit242 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]; }} Proof Yes, return my input

243 © 2007 Herlihy & Shavit243 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]; }} Proof (4) No, return other’s input

244 © 2007 Herlihy & Shavit244 Proof We have displayed –A two-thread consensus protocol –Using any non-trivial RMW object

245 © 2007 Herlihy & Shavit245 Interfering RMW Let F be a set of functions such that for all f i and f j, either –Commute: f i (f j (v))=f j (f i (v)) –Overwrite: f i (f j (v))=f i (v) Claim: Any set of RMW objects that commutes or overwrites has consensus number exactly 2

246 © 2007 Herlihy & Shavit246 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 f i (f j (v))=f i (v) Commute f i (f j (v))= f j (f i (v))

247 © 2007 Herlihy & Shavit247 Meanwhile Back at the Critical State c 0-valent 1-valent A about to apply f A B about to apply f B

248 © 2007 Herlihy & Shavit248 Maybe the Functions Commute c 0-valent A applies f A B applies f B A applies f A B applies f B 01 C runs solo 1-valent

249 © 2007 Herlihy & Shavit249 Maybe the Functions Commute c 0-valent A applies f A B applies f B A applies f A B applies f B 01 C runs solo 1-valent These states look the same to C Contradiction

250 © 2007 Herlihy & Shavit250 Maybe the Functions Overwrite c 0-valent A applies f A B applies f B A applies f A 0 1 C runs solo 1-valent

251 © 2007 Herlihy & Shavit251 Maybe the Functions Overwrite c 0-valent A applies f A B applies f B A applies f A 0 1 C runs solo 1-valent These states look the same to C Contradiction

252 © 2007 Herlihy & Shavit252 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?

253 © 2007 Herlihy & Shavit253 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; } … } compareAndSet

254 © 2007 Herlihy & Shavit254 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; } … } compareAndSet replace value if its what we expected, …

255 © 2007 Herlihy & Shavit255 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()]; } compareAndSet Has ∞ Consensus Number

256 © 2007 Herlihy & Shavit256 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()]; } compareAndSet Has ∞ Consensus Number Initialized to -1

257 © 2007 Herlihy & Shavit257 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()]; } compareAndSet Has ∞ Consensus Number Try to swap in my id

258 © 2007 Herlihy & Shavit258 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()]; } compareAndSet Has ∞ Consensus Number Decide winner’s preference

259 © 2007 Herlihy & Shavit259 The Consensus Hierarchy 1 Read/Write Registers, Snapshots… 2 getAndSet, getAndIncrement, … ∞ compareAndSet,…......

260 © 2007 Herlihy & Shavit260 Multiple Assignment Atomic k-assignment Solves consensus for 2k-2 threads Every even consensus number has an object (can be extended to odd numbers)


Download ppt "Foundations of Shared Memory Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Rajeev Alur for CIS."

Similar presentations


Ads by Google