Вы находитесь на странице: 1из 154

Barrier Synchronization

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

Simple Video Game


Prepare frame for display
By graphics coprocessor

soft real-time application


Need at least 35 frames/second OK to mess up rarely

Art of Multiprocessor Programming

Simple Video Game


while (true) { frame.prepare(); frame.display(); }

Art of Multiprocessor Programming

Simple Video Game


while (true) { frame.prepare(); frame.display(); }

What about overlapping work?


1st thread displays frame 2nd prepares next frame
Art of Multiprocessor Programming 4

Two-Phase Rendering
while (true) { if (phase) { frame[0].display(); } else { frame[1].display(); } phase = !phase; } while (true) { if (phase) { frame[1].prepare(); } else { frame[0].prepare(); } phase = !phase; }

Art of Multiprocessor Programming

Two-Phase Rendering
while (true) { if (phase) { frame[0].display(); } else { frame[1].display(); } phase = !phase; } while (true) { if (phase) { frame[1].prepare(); } else { frame[0].prepare(); } phase = !phase; }

Even phases
Art of Multiprocessor Programming 6

Two-Phase Rendering
while (true) { if (phase) { frame[0].display(); } else { frame[1].display(); } phase = !phase; } while (true) { if (phase) { frame[1].prepare(); } else { frame[0].prepare(); } phase = !phase; }

odd phases
Art of Multiprocessor Programming 7

Synchronization Problems
How do threads stay in phase? Too early?
we render no frame before its time

Too late?
Recycle memory before frame is displayed

Art of Multiprocessor Programming

Ideal Parallel Computation


0 0 0 1 1 1

Art of Multiprocessor Programming

Ideal Parallel Computation


2 2 2 1 1 1

Art of Multiprocessor Programming

10

Real-Life Parallel Computation


0 0 0 zzz 1 1

Art of Multiprocessor Programming

11

Real-Life Parallel Computation


2 zzz 1 1

Uh, oh
Art of Multiprocessor Programming 12

Barrier Synchronization
0 0 0

barrier

Art of Multiprocessor Programming

13

Barrier Synchronization
barrier
1 1 1

Art of Multiprocessor Programming

14

Barrier Synchronization
barrier

Until every thread has left here No thread enters here


Art of Multiprocessor Programming 15

Why Do We Care?
Mostly of interest to
Scientific & numeric computation

Elsewhere
Garbage collection Less common in systems programming Still important topic

Art of Multiprocessor Programming

16

Duality
Dual to mutual exclusion
Include others, not exclude them

Same implementation issues


Interaction with caches
Invalidation? Local spinning?

Art of Multiprocessor Programming

17

Example: Parallel Prefix


a b c d before

after

a+b

a+b+c a+b+c +d

Art of Multiprocessor Programming

18

Parallel Prefix

One thread Per entry

Art of Multiprocessor Programming

19

Parallel Prefix: Phase 1


a b c d

a+b

b+c

c+d

Art of Multiprocessor Programming

20

Parallel Prefix: Phase 2


a b c d

a+b

a+b+c a+b+c +d

Art of Multiprocessor Programming

21

Parallel Prefix
N threads can compute
Parallel prefix Of N entries In log2 N rounds

What if system is asynchronous?


Why we need barriers

Art of Multiprocessor Programming

22

Prefix
class Prefix extends Thread { int[] a; int i; Barrier b; void Prefix(int[] a, Barrier b, int i) { a = a; b = b; i = i; }
Art of Multiprocessor Programming 23

Prefix
class Prefix extends Thread { int[] a; int i; Barrier b; void Prefix(int[] a, Barrier b, int i) { a = a; Array of input b = b; values i = i; }
Art of Multiprocessor Programming 24

Prefix
class Prefix extends Thread { int[] a; int i; Barrier b; void Prefix(int[] a, Barrier b, int i) { a = a; Thread index b = b; i = i; }
Art of Multiprocessor Programming 25

Prefix
class Prefix extends Thread { int[] a; int i; Barrier b; void Prefix(int[] a, Barrier b, int i) { a = a; Shared barrier b = b; i = i; }
Art of Multiprocessor Programming 26

Prefix
class Prefix extends Thread { int[] a; int i; Initialize fields Barrier b; void Prefix(int[] a, Barrier b, int i) { a = a; b = b; i = i; }
Art of Multiprocessor Programming 27

Where Do the Barriers Go?


public void run() { int d = 1, sum = 0; while (d < N) { if (i >= d) sum = a[i-d]; if (i >= d) a[i] += sum; d = d * 2; }}}

Art of Multiprocessor Programming

28

Where Do the Barriers Go?


public void run() { int d = 1, sum = 0; while (d < N) { if (i >= d) sum = a[i-d]; b.await(); if (i >= d) a[i] += sum; d = d * 2; }}}

Art of Multiprocessor Programming

29

Where Do the Barriers Go?


public void run() { int d = 1, sum = 0; while (d < N) { if (i >= d) sum = a[i-d]; Make sure everyone reads b.await(); before anyone writes if (i >= d) a[i] += sum; d = d * 2; }}}

Art of Multiprocessor Programming

30

Where Do the Barriers Go?


public void run() { int d = 1, sum = 0; while (d < N) { if (i >= d) sum = a[i-d]; Make sure everyone reads b.await(); before anyone writes if (i >= d) a[i] += sum; b.await(); d = d * 2; }}}
Art of Multiprocessor Programming 31

Where Do the Barriers Go?


public void run() int d = 1, sum = while (d < N) { if (i >= d) sum = a[i-d]; b.await(); if (i >= d) a[i] += sum; b.await(); d = d * 2; }}} { 0;

Make sure everyone reads before anyone writes


Make sure everyone writes before anyone reads

Art of Multiprocessor Programming

32

Barrier Implementations
Cache coherence
Spin on locally-cached locations? Spin on statically-defined locations?

Latency
How many steps?

Symmetry
Do all threads do the same thing?
Art of Multiprocessor Programming 33

Barriers
public class Barrier { AtomicInteger count; int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

34

Barriers
public class Barrier { AtomicInteger count; int size; public Barrier(int n){ count = AtomicInteger(n); Number threads size = n; not yet arrived } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

35

Barriers
public class Barrier { AtomicInteger count; int size; Number threads public Barrier(int n){ participating count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

36

Barriers
public class Barrier { Initialization AtomicInteger count; int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

37

Barriers
public class Barrier { AtomicInteger count; Principal method int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

38

Barriers
public class Barrier { If Im last, reset AtomicInteger count; fields for next time int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

39

Barriers
public class Barrier { AtomicInteger count;Otherwise, wait for int size; everyone else public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

40

Barriers
public class Barrier { AtomicInteger count; int size; public Barrier(int n){ count = AtomicInteger(n); size = n; Whats wrong with this protocol? } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

41

Reuse
Barrier b = new Barrier(n); while ( mumble() ) { Do work work(); repeat synchronize b.await() }

Art of Multiprocessor Programming

42

Barriers
public class Barrier { AtomicInteger count; int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

43

Barriers
public class Barrier { AtomicInteger count; Waiting for Phase 1 to finish int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}}
Programming

44

Barriers
Phase 1 public class Barrier { is so over AtomicInteger count; Waiting for Phase 1 to finish int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}} Programming

45

Barriers
Prepare for public class Barrier { phase 2 ZZZZZ. AtomicInteger count; int size; public Barrier(int n){ count = AtomicInteger(n); size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}} Programming

46

Uh-Oh
public class Barrier { Waiting for AtomicInteger count; Phase 2 to finish int size; public Barrier(int n){ Waiting for count = AtomicInteger(n); Phase 1 to finish size = n; } public void await() { if (count.getAndDecrement()==1) { count.set(size); } else { while (count.get() != 0); Art of Multiprocessor }}}} Programming

Basic Problem
One thread wraps around to start phase 2 While another thread is still waiting for phase 1 One solution:
Always use two barriers

Art of Multiprocessor Programming

48

Sense-Reversing Barriers
public class Barrier { AtomicInteger count; int size; boolean sense = false; threadSense = new ThreadLocal<boolean> public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 49

Sense-Reversing Barriers
public class Barrier { Completed odd or AtomicInteger count; even-numbered int size; boolean sense = false; phase? threadSense = new ThreadLocal<boolean> public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 50

Sense-Reversing Barriers
public class Barrier { Store sense for AtomicInteger count; next phase int size; boolean sense = false; threadSense = new ThreadLocal<boolean> public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 51

Sense-Reversing Barriers
public class Barrier { AtomicInteger count; int size; Get new sense determined boolean sense = false; by last phase threadSense = new ThreadLocal<boolean> public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 52

Sense-Reversing Barriers
public class Barrier { AtomicInteger count; int size; boolean sense = false; If Im last, reverse threadSense = new ThreadLocal<boolean>

sense for next time

public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 53

Sense-Reversing Barriers
public class Barrier { AtomicInteger count; Otherwise, wait for int size; sense to flip boolean sense = false; threadSense = new ThreadLocal<boolean> public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 54

Sense-Reversing Barriers
public class Barrier { AtomicInteger count; Prepare sense for next int size; phase boolean sense = false; threadSense = new ThreadLocal<boolean> public void await { boolean mySense = threadSense.get(); if (count.getAndDecrement()==1) { count.set(size); sense = mySense } else { while (sense != mySense) {} } threadSense.set(!mySense)}}}
Art of Multiprocessor Programming 55

Combining Tree Barriers


2-barrier

2-barrier

2-barrier

Art of Multiprocessor Programming

56

Combining Tree Barriers


2-barrier

2-barrier

2-barrier

Art of Multiprocessor Programming

57

Combining Tree Barrier


public class Node{ AtomicInteger count; int size; Node parent; volatile boolean sense; public void await() { if (count.getAndDecrement()==1) { if (parent != null) parent.await() count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 58

Combining Tree Barrier


Parent barrier in public class Node{ AtomicInteger count; int size; tree Node parent; volatile boolean sense;
public void await() { if (count.getAndDecrement()==1) { if (parent != null) parent.await() count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 59

Combining Tree Barrier


Am I last? public class Node{ AtomicInteger count; int size; Node parent; volatile boolean sense;
public void await() { if (count.getAndDecrement()==1) { if (parent != null) parent.await() count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 60

Combining Tree Barrier


public class Node{ Proceed to parent barrier AtomicInteger count; int size; Node parent; volatile boolean sense; public void await() { if (count.getAndDecrement()==1) { if (parent != null) parent.await(); count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 61

Combining Tree Barrier


public class Node{ Prepare for next phase AtomicInteger count; int size; Node parent; volatile boolean sense; public void await() { if (count.getAndDecrement()==1) { if (parent != null) parent.await() count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 62

Combining Tree Barrier


public class Node{ Notify others at this node AtomicInteger count; int size; Node parent; volatile boolean sense; public void await() { if (count.getAndDecrement()==1) { if (parent != null) parent.await() count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 63

Combining Tree Barrier


public class Node{ Im not last, so wait for AtomicInteger count; int size; notification Node parent; volatile boolean sense; public void await() { if (count.getAndDecrement()==1) { if (parent != null) { parent.await() count.set(size); sense = mySense } else { while (sense != mySense) {} }}}}
Art of Multiprocessor Programming 64

Combining Tree Barrier


No sequential bottleneck
Parallel getAndDecrement() calls

Low memory contention


Same reason

Cache behavior
Local spinning on bus-based architecture Not so good for NUMA
Art of Multiprocessor Programming 65

Remarks
Everyone spins on sense field
Local spinning on bus-based (good) Network hot-spot on distributed architecture (bad)

Not really scalable

Art of Multiprocessor Programming

66

Tournament Tree Barrier


If tree nodes have fan-in 2
Dont need to call getAndDecrement() Winner chosen statically

At level i
If i-th bit of id is 0, move up Otherwise keep back

Art of Multiprocessor Programming

67

Tournament Tree Barriers


root

winner

loser

winner

loser

winner
Art of Multiprocessor Programming

loser
68

Tournament Tree Barriers

All flags blue

Art of Multiprocessor Programming

69

Tournament Tree Barriers

Loser thread sets winners flag


Art of Multiprocessor Programming 70

Tournament Tree Barriers

Loser spins on own flag


Art of Multiprocessor Programming 71

Tournament Tree Barriers

Winner spins on own flag


Art of Multiprocessor Programming 72

Tournament Tree Barriers

Winner sees own flag, moves up, spins


Art of Multiprocessor Programming 73

Tournament Tree Barriers


Bingo!

Art of Multiprocessor Programming

74

Tournament Tree Barriers

Sense-reversing: next time use blue flags

Art of Multiprocessor Programming

75

Tournament Barrier
class TBarrier { boolean flag; TBarrier partner; TBarrier parent; boolean top; }

Art of Multiprocessor Programming

76

Tournament Barrier
class TBarrier { boolean flag; TBarrier partner; TBarrier parent; boolean top; }

Notifications delivered here

Art of Multiprocessor Programming

77

Tournament Barrier
class TBarrier { boolean flag; TBarrier partner; TBarrier parent; boolean top; }

Other thead at same level

Art of Multiprocessor Programming

78

Tournament Barrier
class TBarrier { boolean flag; TBarrier partner; TBarrier parent; boolean top; }

Parent (winner) or null (loser)

Art of Multiprocessor Programming

79

Tournament Barrier
class TBarrier { boolean flag; TBarrier partner; TBarrier parent; boolean top; }

Am I the root?

Art of Multiprocessor Programming

80

Tournament Barrier
void await(boolean mySense) { if (top) { return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 81

Tournament Barrier
void await(boolean mySense) { if (top) { return; Le root, cest moi } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming

Current sense

82

Tournament Barrier
void await(boolean mySense) { I am already a if (top) { winner return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 83

Tournament Barrier
void await(boolean mySense) { Wait for partner if (top) { return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 84

Tournament Barrier
void await(boolean mySense) { if (top) { Synchronize upstairs return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 85

Tournament Barrier
void await(boolean mySense) { if (top) { Inform partner return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 86

Tournament Barrier
void await(boolean mySense) { if (top) { Inform partner return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; Order is important (why?) }}}
Art of Multiprocessor Programming 87

Tournament Barrier
void await(boolean mySense) { if (top) { Natural-born loser return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 88

Tournament Barrier
void await(boolean mySense) { if (top) { Tell partner Im here return; } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 89

Tournament Barrier
void await(boolean mySense) { if (top) { Wait for notification return; from partner } else if (parent != null) { while (flag != mySense) {}; parent.await(mySense); partner.flag = mySense; } else { partner.flag = mySense; while (flag != mySense) {}; }}}
Art of Multiprocessor Programming 90

Remarks
No need for read-modify-write calls Each thread spins on fixed location
Good for bus-based architectures Good for NUMA architectures

Art of Multiprocessor Programming

91

Dissemination Barrier
At round i
Thread A notifies thread A+2i (mod n)

Requires log n rounds

Art of Multiprocessor Programming

92

Dissemination Barrier
+1 +2 +4

Art of Multiprocessor Programming

93

Remarks
Elegant Good source of homework problems Not cache-friendly

Art of Multiprocessor Programming

94

Ideas So Far
Sense-reversing
Combining tree
Reuse without reinitializing

Tournament tree

Like counters, locks


Optimized combining tree Intellectually Pleasing (matter of taste)
Art of Multiprocessor Programming 95

Dissemination barrier

Which is best for Multicore?


On a cache coherent multicore chip: perhaps none of the above Here is another (arguably) better algorithm

Art of Multiprocessor Programming

96

Static Tree Barrier

Art of Multiprocessor Programming

One node per thread, statically assigned


97

Static Tree Barrier


Sense-reversing flag

Art of Multiprocessor Programming

98

Static Tree Barrier


2

Node has count of missing children


Art of Multiprocessor Programming 99

Static Tree Barrier


Spin until zero
2 2

Art of Multiprocessor Programming

100

Static Tree Barrier


2

2 1

My counter is zero, 0 decrement parent


Art of Multiprocessor Programming 101

Static Tree Barrier


2

2 1

Spin on Done 0 flag

Art of Multiprocessor Programming

102

Static Tree Barrier


1 2

2 1

Art of Multiprocessor Programming

103

Static Tree Barrier


1 2

2 1

Art of Multiprocessor Programming

104

Static Tree Barrier


1 2

2 1

Art of Multiprocessor Programming

105

Static Tree Barrier


1 2

0 1

Art of Multiprocessor Programming

106

Static Tree Barrier


1 2

0 1

Art of Multiprocessor Programming

107

Static Tree Barrier


yowzah!

1 0

0 1

Art of Multiprocessor Programming

108

Static Tree Barrier yowzah!


1 0

0 1

Art of Multiprocessor Programming

109

Static Tree Barrier yowzah!


1 0

0 1

Art of Multiprocessor Programming

110

yes! yes!

Static Tree Barrier


1 0

0 1

yes!

yes!

yes!

Art of Multiprocessor Programming

111

Static Tree Barrier


1 2

2 1

Art of Multiprocessor Programming

112

Remarks
Very little cache traffic Minimal space overhead On message-passing architecture
Send notification & sense down tree

Art of Multiprocessor Programming

113

The Nature of Progress*

Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit
* See Chapter 3 in the textbook and http: //www.cs.tau.ac.il/~shanir/progress.pdf

Concurrent Programming
Many real-word data structures
blocking (lock-based) implementations & non-blocking (no locks) implementations

For example:
linked lists, queues, stacks, hash maps,

115

Concurrent Programming
Many data structures combine blocking & non-blocking methods Java concurrency package
skiplists, hash tables, exchangers on 10 million desktops.

116

Progress Conditions
Deadlock-free: Starvation-free: Lock-free:
Some thread eventually acquires lock. Every thread eventually acquires lock.

Wait-free:

Some method call returns.


Every method call returns. Every method call returns if it executes in isolation

Obstruction-free:

We will show an example shortly

117

List-Based Sets
Unordered collection of elements No duplicates Methods
Add() a new element Remove() an element Contains() if element is present

118

Coarse Grained Locking

b c

Lock is starvation-free: every attempt to acquire the lock eventually succeeds.


119

Fine Grained (Lock Coupling)


a Overlapping locks detect overlapping operations b c d

Deadlock-free: some thread eventually acquires lock.


120

Optimistic Fine Grained


a b c e

Add(), Remove(), contains() lock destination nodes in order Deadlock-free: some thread trying to acquire the locks eventually succeeds.
121

Obstruction-free contains()
a b c d

Snapshot: if all nodes traversed twice are the same Obstruction-free: the method returns if it executes in isolation for long enough.
122

The Simple Snapshot is Obstruction-Free


Put increasing labels on each entry Collect twice If both agree,
Were done
Collect1 1 22 1 7 13 18 12

Collect2
1

Otherwise,
Try again

22 1 7 13 18 12 123

Obstruction-freedom
In the simple snapshot alg:
The update method is wait-free But scan is obstruction-free
Completes if it executes in isolation (no concurrent updates).

124

Wait-free contains()
d 0 c1 e 0

a 0

b 0

Use mark bit + list ordering 1. Not marked in the set 2. Marked or missing not in the set
125

Lazy List-based Set Alg


d 0 c1 e 0

a 0

b 0

Combine blocking and non-blocking: deadlockfree Add() and Remove() and wait-free Contains()
126

Lock-free Algorithm
Logical Removal = Set Mark Bit

a 0

b 0

c 0 c1 d 0

e 0

mark and reference CASed together

CAS will fail

Lock-free Add() and Remove(), and wait-free Contains().


127

So how can this make sense?


Why have methods with different progress conditions? Let us try to understand this

Art of Multiprocessor Programming Copyright

128

Progress Conditions
Deadlock-free: Starvation-free: Lock-free:
Some thread eventually acquires lock. Every thread eventually acquires lock.

Wait-free:

Some method call returns.


Every method call returns. Every method call returns if it executes in isolation
129

Obstruction-free:

A Periodic Table of Progress Conditions


Non-Blocking All make progress Some make progress Waitfree Lockfree Blocking

Obstruction- Starvationfree free


Deadlockfree

130

More Formally
Standard notion of abstract object Progress conditions relate to method calls of an object

A thread is active if it takes an infinite number of concrete (machine level) steps And is suspended if not.

131

Maximal vs. Minimal


Minimal progress
some call eventually completes System matters, not individuals

Maximal progress
every call eventually completes. Individuals matter
Flags courtesy of www.theodora.com/flags used with permission

132

The Periodic Table of Progress Conditions


Non-Blocking Maximal progress
Minimal progress Waitfree

Blocking

Obstruction- Starvationfree free

Lockfree

Deadlockfree
133

The Schedulers Role


Multiprocessor progress properties:

Are not about the guarantees a method's implementation provides.


Are about scheduling needed to provide minimal or maximal progress.

134

Fair Scheduling
A history is fair if each thread takes an infinite number of steps A method implementation is deadlock-free if it guarantees minimal progress in every fair history.
135

Starvation Freedom
A method implementation is starvation-free if it guarantees maximal progress in every fair history.

136

Dependent Progress
Dependent progress conditions
Do not guarantee minimal progress in every history

Independent ones do. Blocking progress conditions

deadlock-freedom, Starvation-freedom are dependent.

137

Non-blocking Independent Conditions


A lock-free method guarantees
minimal progress in every history. maximal progress in every history.

A wait-free method guarantees

138

A Periodic Table of Progress Conditions


Non-Blocking Maximal progress Minimal progress Waitfree Lockfree

Blocking

Obstruction- Starvationfree free


Deadlockfree Dependent
139

Independent

Uniformly Isolating Schedules


A history is uniformly isolating if any thread eventually runs by itself for long enough Modern systems do this with backoff, yield, etc.

140

A Non-blocking Dependent Condition


A method implementation is obstruction-free if it guarantees
maximal progress in every uniformly isolating history.

141

The Periodic Table of Progress Conditions


Non-Blocking Maximal progress Minimal progress Waitfree Lockfree

Blocking

Uniform iso Obstruction- Starvationscheduler Fair scheduler

free

free

DeadlockFair scheduler free

Independent

Dependent

142

The Periodic Table of Progress Conditions


Non-Blocking Maximal progress Minimal progress Waitfree Lockfree

Blocking

Obstruction- Starvationfree free


Clashfree

Deadlockfree

Independent

Dependent

143

Clash-Freedom: the Einsteinium of Progress


A method implementation is clash-free if it guarantees
minimal progress in every uniformly isolating history.

Thm: clash-freedom strictly weaker than obstruction-freedom

144

Getting from Minimal to Maximal


Non-Blocking Maximal progress Minimal progress Waitfree Lockfree

Blocking

Obstruction- Starvationfree free


Clashfree

Deadlock- Helping free

Independent

Dependent

145

Maximal Progress Postulate


Programmers want maximal progress.

Methods progress conditions define


What we expect from the scheduler For example
Dont halt in critical section Let me run in isolation long enough

s149

Why Lock-Free is OK
We all want maximal progress
Wait-free

Yet we often write lock-free or lockbased algorithms OK if we expect the scheduler to be benevolent
Often true (not always!)
Art of Multiprocessor Programming 150

Shared-Memory Computability

Shared Memory

10011

What is (and is not) concurrently computable Wait-free Atomic Registers Lock-free/Wait-free Hierarchy and Universal Constructions
151

Troubling Intellectual Question

I think I think, therefore I think I am (Ambrose Bierce)

Why use non-blocking lock-free and wait-free conditions when most code uses locks?

152

The Answer
Not about being non-blocking About being independent! Do not rely on the good behavior of the scheduler.

153

By Analogy to Church-Turing
abanbnan
Finite State Controller Reads and Writes 10 1 1 0 1 0 Infinite tape

Using a dependent condition is like relying on an oracle to recognize languages The dependency masks the true power of the concurrent object
154

Shared-Memory Computability

Shared Memory

10011

Independent progress: use Lock-free and Wait-free Memory Hierarchy and Universal Constructions

155

Summary
Table explains how conditions fit together Justifies common assumptions We expect maximal progress. Progress conditions define scheduler requirements.

156

This work is licensed under a Creative Commons AttributionShareAlike 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

157

Вам также может понравиться