Mutual Exclusion Companion slides for The Art of

  • Slides: 76
Download presentation
Mutual Exclusion Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy &

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

Mutual Exclusion • Today we will try to formalize our understanding of mutual exclusion

Mutual Exclusion • Today we will try to formalize our understanding of mutual exclusion • We will also use the opportunity to show you how to argue about and prove various properties in an asynchronous concurrent setting Art of Multiprocessor Programming 2

Mutual Exclusion • • • Formal problem definitions Solutions for 2 threads Solutions for

Mutual Exclusion • • • Formal problem definitions Solutions for 2 threads Solutions for n threads Fair solutions Inherent costs Art of Multiprocessor Programming 4

Warning • You will never use these protocols – Get over it • You

Warning • You will never use these protocols – Get over it • You are advised to understand them – The same issues show up everywhere – Except hidden and more complex Art of Multiprocessor Programming 5

Why is Concurrent Programming so Hard? • Try preparing a seven-course banquet – By

Why is Concurrent Programming so Hard? • Try preparing a seven-course banquet – By yourself – With one friend – With twenty-seven friends … • Before we can talk about programs – Need a language – Describing time and concurrency Art of Multiprocessor Programming 6

Events • An event a 0 of thread A is – Instantaneous – No

Events • An event a 0 of thread A is – Instantaneous – No simultaneous events (break ties) a 0 time Art of Multiprocessor Programming 8

Threads • A thread A is (formally) a sequence a 0, a 1, .

Threads • A thread A is (formally) a sequence a 0, a 1, . . . of events – “Trace” model – Notation: a 0 a 1 indicates order a 0 a 1 a 2 … time Art of Multiprocessor Programming 9

Example Thread Events • • • Assign to shared variable Assign to local variable

Example Thread Events • • • Assign to shared variable Assign to local variable Invoke method Return from method Lots of other things … Art of Multiprocessor Programming 10

Concurrency • Thread A time Art of Multiprocessor Programming 13

Concurrency • Thread A time Art of Multiprocessor Programming 13

Concurrency • Thread A time • Thread B time Art of Multiprocessor Programming 14

Concurrency • Thread A time • Thread B time Art of Multiprocessor Programming 14

Interleavings • Events of two or more threads – Interleaved – Not necessarily independent

Interleavings • Events of two or more threads – Interleaved – Not necessarily independent (why? ) time Art of Multiprocessor Programming 15

Intervals • An interval A 0 =(a 0, a 1) is – Time between

Intervals • An interval A 0 =(a 0, a 1) is – Time between events a 0 and a 1 a 0 A 0 a 1 time Art of Multiprocessor Programming 16

Intervals may Overlap b 0 a 0 A 0 B 0 b 1 a

Intervals may Overlap b 0 a 0 A 0 B 0 b 1 a 1 time Art of Multiprocessor Programming 17

Intervals may be Disjoint b 0 a 0 A 0 B 0 b 1

Intervals may be Disjoint b 0 a 0 A 0 B 0 b 1 a 1 time Art of Multiprocessor Programming 18

Precedence Interval A 0 precedes interval B 0 b 0 a 0 A 0

Precedence Interval A 0 precedes interval B 0 b 0 a 0 A 0 B 0 b 1 a 1 time Art of Multiprocessor Programming 19

Precedence • Notation: A 0 B 0 • Formally, – End event of A

Precedence • Notation: A 0 B 0 • Formally, – End event of A 0 before start event of B 0 – Also called “happens before” or “precedes” Art of Multiprocessor Programming 20

Precedence Ordering • Remark: A 0 B 0 is just like saying – 1066

Precedence Ordering • Remark: A 0 B 0 is just like saying – 1066 AD 1492 AD, – Middle Ages Renaissance, • Oh wait, – what about this week vs this month? Art of Multiprocessor Programming 21

Precedence Ordering • • Never true that A A If A B then not

Precedence Ordering • • Never true that A A If A B then not true that B A If A B & B C then A C Funny thing: A B & B A might both be false! Art of Multiprocessor Programming 22

Implementing a Counter public class Counter { private long value; public long get. And.

Implementing a Counter public class Counter { private long value; public long get. And. Increment() { temp = value; value = temp + 1; return temp; Make these } } steps indivisible using locks Art of Multiprocessor 26 Programming

Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); }

Locks (Mutual Exclusion) public interface Lock { public void lock(); public void unlock(); } Art of Multiprocessor Programming 27

Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void

Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void unlock(); } Art of Multiprocessor Programming 28

Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void

Locks (Mutual Exclusion) public interface Lock { public void lock(); acquire lock public void unlock(); release lock } Art of Multiprocessor Programming 29

Using Locks public class Counter { private long value; private Lock lock; public long

Using Locks public class Counter { private long value; private Lock lock; public long get. And. Increment() { lock(); try { int temp = value; value = value + 1; } finally { lock. unlock(); } return temp; }} Art of Multiprocessor Programming 30

Using Locks public class Counter { private long value; private Lock lock; public long

Using Locks public class Counter { private long value; private Lock lock; public long get. And. Increment() { lock(); acquire try { int temp = value; value = value + 1; } finally { lock. unlock(); } return temp; }} Art of Multiprocessor Programming Lock 31

Using Locks public class Counter { private long value; private Lock lock; public long

Using Locks public class Counter { private long value; private Lock lock; public long get. And. Increment() { lock(); try { int temp = value; value = value + 1; } finally { Release lock. unlock(); } (no matter what) return temp; }} Art of Multiprocessor Programming 32

Using Locks public class Counter { private long value; private Lock lock; public long

Using Locks public class Counter { private long value; private Lock lock; public long get. And. Increment() { lock(); try { int temp = value; value = value + 1; } finally { lock. unlock(); } return temp; }} Art of Multiprocessor Programming Critical section 33

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution Art of

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution Art of Multiprocessor Programming 34

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be thread j’s m-th critical section execution Art of Multiprocessor Programming 35

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or Art of Multiprocessor Programming 36

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or CSik CSjm Art of Multiprocessor Programming 37

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And

Mutual Exclusion • Let CSik be thread i’s k-th critical section execution • And CSjm be j’s m-th execution • Then either – or CSik CSjm Art of Multiprocessor Programming CSjm CSik 38

Deadlock-Free • If some thread calls lock() – And never returns – Then other

Deadlock-Free • If some thread calls lock() – And never returns – Then other threads must complete lock() and unlock() calls infinitely often • System as a whole makes progress – Even if individuals starve Art of Multiprocessor Programming 39

Starvation-Free • If some thread calls lock() – It will eventually return • Individual

Starvation-Free • If some thread calls lock() – It will eventually return • Individual threads make progress Art of Multiprocessor Programming 40

Two-Thread vs n -Thread Solutions • Two-thread solutions first – Illustrate most basic ideas

Two-Thread vs n -Thread Solutions • Two-thread solutions first – Illustrate most basic ideas – Fits on one slide • Then n-Thread solutions Art of Multiprocessor Programming 41

Two-Thread Conventions class … implements Lock { … // thread-local index, 0 or 1

Two-Thread Conventions class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = Thread. ID. get(); int j = 1 - i; … } } Art of Multiprocessor Programming 42

Two-Thread Conventions class … implements Lock { … // thread-local index, 0 or 1

Two-Thread Conventions class … implements Lock { … // thread-local index, 0 or 1 public void lock() { int i = Thread. ID. get(); int j = 1 - i; … } } Henceforth: i is current thread, j is other thread Art of Multiprocessor Programming 43

Lock. One class Lock. One implements Lock { private boolean[] flag = new boolean[2];

Lock. One class Lock. One implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} } Art of Multiprocessor Programming 44

Lock. One class Lock. One implements Lock { private boolean[] flag = new boolean[2];

Lock. One class Lock. One implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} Set my flag } Art of Multiprocessor Programming 45

Lock. One class Lock. One implements Lock { private boolean[] flag = new boolean[2];

Lock. One class Lock. One implements Lock { private boolean[] flag = new boolean[2]; public void lock() { flag[i] = true; while (flag[j]) {} Set my flag } Wait for other flag to go false Art of Multiprocessor Programming 46

Lock. One Satisfies Mutual Exclusion • Assume CSAj overlaps CSBk • Consider each thread's

Lock. One Satisfies Mutual Exclusion • Assume CSAj overlaps CSBk • Consider each thread's last (j-th and k-th) read and write in the lock() method before entering • Derive a contradiction Art of Multiprocessor Programming 47

Deadlock Freedom • Lock. One Fails deadlock-freedom – Concurrent execution can deadlock flag[i] =

Deadlock Freedom • Lock. One Fails deadlock-freedom – Concurrent execution can deadlock flag[i] = true; while (flag[j]){} flag[j] = true; while (flag[i]){} – Sequential executions OK Art of Multiprocessor Programming 57

Peterson’s Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j]

Peterson’s Algorithm public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Art of Multiprocessor Programming 63

Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; victim =

Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Art of Multiprocessor Programming 64

Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; Defer to

Peterson’s Algorithm Announce I’m interested public void lock() { flag[i] = true; Defer to other victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Art of Multiprocessor Programming 65

Peterson’s Algorithm Announce I’m interested Defer to other public void lock() { flag[i] =

Peterson’s Algorithm Announce I’m interested Defer to other public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { Wait while other flag[i] = false; interested & I’m } the victim Art of Multiprocessor Programming 66

Peterson’s Algorithm Announce I’m interested Defer to other public void lock() { flag[i] =

Peterson’s Algorithm Announce I’m interested Defer to other public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { Wait while other flag[i] = false; interested & I’m } the victim No longer interested Art of Multiprocessor Programming 67

Mutual Exclusion public void lock() { flag[i] = true; victim = i; while (flag[j]

Mutual Exclusion public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; • If thread 0 in critical section, – flag[0]=true, – victim = 1 • If thread 1 in critical section, – flag[1]=true, – victim = 0 Cannot both be true Art of Multiprocessor Programming 68

Deadlock Free public void lock() { … while (flag[j] && victim == i) {};

Deadlock Free public void lock() { … while (flag[j] && victim == i) {}; • Thread blocked – only at while loop – only if it is the victim • One or the other must not be the victim Art of Multiprocessor Programming 69

Starvation Free • Thread i blocked only if j repeatedly re-enters so that flag[j]

Starvation Free • Thread i blocked only if j repeatedly re-enters so that flag[j] == true victim == i and • When j re-enters – it sets victim to j. – So i gets in public void lock() { flag[i] = true; victim = i; while (flag[j] && victim == i) {}; } public void unlock() { flag[i] = false; } Art of Multiprocessor Programming 70

The Filter Algorithm for n Threads There are n-1 “waiting rooms” called levels ncs

The Filter Algorithm for n Threads There are n-1 “waiting rooms” called levels ncs • At each level – At least one enters level – At least one blocked if many try cs • Only one thread makes it through Art of Multiprocessor Programming 71

Bakery Algorithm • Provides First-Come-First-Served • How? – Take a “number” – Wait until

Bakery Algorithm • Provides First-Come-First-Served • How? – Take a “number” – Wait until lower numbers have been served • Lexicographic order – (a, i) > (b, j) • If a > b, or a = b and i > j Art of Multiprocessor Programming 93

Bakery Algorithm class Bakery implements Lock { boolean[] flag; Label[] label; public Bakery (int

Bakery Algorithm class Bakery implements Lock { boolean[] flag; Label[] label; public Bakery (int n) { flag = new boolean[n]; label = new Label[n]; for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } } … Art of Multiprocessor Programming 94

Bakery Algorithm class Bakery implements Lock { boolean[] flag; 6 Label[] label; 2 0

Bakery Algorithm class Bakery implements Lock { boolean[] flag; 6 Label[] label; 2 0 n-1 public Bakery (int n) { flag = new boolean[n]; f f t f f label = new Label[n]; 0 0 4 0 0 5 0 0 for (int i = 0; i < n; i++) { flag[i] = false; label[i] = 0; } } … CS Art of Multiprocessor Programming 95

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock {

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 96

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock {

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Doorway lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 97

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock {

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { I’m interested lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 98

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock {

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Take increasing label (read labels in some arbitrary order) lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 99

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock {

Bakery Algorithm class Bakery … public void flag[i] = label[i] = implements Lock { Someone is interested lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 100

Bakery Algorithm class Bakery implements Lock { boolean flag[n]; Someone int label[n]; is interested

Bakery Algorithm class Bakery implements Lock { boolean flag[n]; Someone int label[n]; is interested public void lock() { flag[i] = true; label[i] = max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } With lower (label, i) in lexicographic order Art of Multiprocessor Programming 101

Bakery Algorithm class Bakery implements Lock { … public void unlock() { flag[i] =

Bakery Algorithm class Bakery implements Lock { … public void unlock() { flag[i] = false; } } Art of Multiprocessor Programming 102

Bakery Algorithm class Bakery implements Lock { … No longer interested public void unlock()

Bakery Algorithm class Bakery implements Lock { … No longer interested public void unlock() { flag[i] = false; } } labels are always increasing Art of Multiprocessor Programming 103

No Deadlock • There is always one thread with earliest label • Ties are

No Deadlock • There is always one thread with earliest label • Ties are impossible (why? ) Art of Multiprocessor Programming 104

Mutual Exclusion • Suppose A and B in CS together • Suppose A has

Mutual Exclusion • Suppose A and B in CS together • Suppose A has earlier label • When B entered, it must have seen class Bakery implements Lock { public void lock() { flag[i] = true; label[i] = max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } – flag[A] is false, or – label[A] > label[B] Art of Multiprocessor Programming 106

Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A]

Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false Art of Multiprocessor Programming 107

Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A]

Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false • Labeling. B read. B(flag[A]) write. A(flag[A]) Labeling. A Art of Multiprocessor Programming 108

Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A]

Mutual Exclusion • Labels are strictly increasing so • B must have seen flag[A] == false • Labeling. B read. B(flag[A]) write. A(flag[A]) Labeling. A • Which contradicts the assumption that A has an earlier label Art of Multiprocessor Programming 109

Bakery Y 232 K Bug class Bakery … public void flag[i] = label[i] =

Bakery Y 232 K Bug class Bakery … public void flag[i] = label[i] = implements Lock { lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 110

Bakery Y 232 K Bug class Bakery … public void flag[i] = label[i] =

Bakery Y 232 K Bug class Bakery … public void flag[i] = label[i] = Mutex breaks if label[i] overflows implements Lock { lock() { true; max(label[0], …, label[n-1])+1; while ($k flag[k] && (label[i], i) > (label[k], k)); } Art of Multiprocessor Programming 111

Does Overflow Actually Matter? • Yes – Y 2 K – 18 January 2038

Does Overflow Actually Matter? • Yes – Y 2 K – 18 January 2038 (Unix time_t rollover) – 16 -bit counters • No – 64 -bit counters • Maybe – 32 -bit counters Art of Multiprocessor Programming 112

Timestamps • Label variable is really a timestamp • Need ability to – Read

Timestamps • Label variable is really a timestamp • Need ability to – Read others’ timestamps – Compare them – Generate a later timestamp • Can we do this without overflow? Art of Multiprocessor Programming 113

The Good News • One can construct a – – Wait-free (no mutual exclusion)

The Good News • One can construct a – – Wait-free (no mutual exclusion) Concurrent Timestamping system That never overflows Art of Multiprocessor Programming 114

The Good News • The Bakery Algorithm is – Succinct, – Elegant, and –

The Good News • The Bakery Algorithm is – Succinct, – Elegant, and – Fair. • Q: So why isn’t it practical? • A: Well, you have to read N distinct variables Art of Multiprocessor Programming 115

d a The Good News B • One can construct a – – Wait-free

d a The Good News B • One can construct a – – Wait-free (no mutual exclusion) This part Concurrent Timestamping system That never overflows Art of Multiprocessor Programming is hard 116

Instead … • We construct a Sequential timestamping system – Same basic idea –

Instead … • We construct a Sequential timestamping system – Same basic idea – But simpler • Uses mutex to read & write atomically • No good for building locks – But useful anyway Art of Multiprocessor Programming 117

Deep Philosophical Question • The Bakery Algorithm is – Succinct, – Elegant, and –

Deep Philosophical Question • The Bakery Algorithm is – Succinct, – Elegant, and – Fair. • Q: So why isn’t it practical? • A: Well, you have to read N distinct variables Art of Multiprocessor Programming 134

 This work is licensed under a Creative Commons Attribution. Share. Alike 2. 5

This work is licensed under a Creative Commons Attribution. Share. Alike 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 159