Linked Lists: Lazy and Non-Blocking Synchronization Based on the companion slides for The Art of Multiprocessor Programming (Maurice Herlihy & Nir Shavit)

Post on 16-Dec-2015

220 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

Transcript

Linked Lists: Lazy and Non-Blocking Synchronization

Based on the companion slides forThe Art of Multiprocessor

Programming(Maurice Herlihy & Nir Shavit)

Art of Multiprocessor Programming© Herlihy-Shavit 2007 2

Lazy List

• Like optimistic, except– Scan once– contains(x) never locks …

• Key insight– Removing nodes causes trouble– Do it “lazily”

Art of Multiprocessor Programming© Herlihy-Shavit 2007 3

Lazy List

• remove()– Scans list (as before)– Locks predecessor & current (as before)

• Logical delete– Marks current node as removed (new!)

• Physical delete– Redirects predecessor’s next (as before)

Art of Multiprocessor Programming© Herlihy-Shavit 2007 4

Lazy Removal

aa b c d

Art of Multiprocessor Programming© Herlihy-Shavit 2007 5

Lazy Removal

aa b c d

Present in list

Art of Multiprocessor Programming© Herlihy-Shavit 2007 6

Lazy Removal

aa b c d

Logically deleted

Art of Multiprocessor Programming© Herlihy-Shavit 2007 7

Lazy Removal

aa b c d

Physically deleted

Art of Multiprocessor Programming© Herlihy-Shavit 2007 8

Lazy Removal

aa b d

Physically deleted

Art of Multiprocessor Programming© Herlihy-Shavit 2007 9

Lazy List

• All Methods– Scan through locked and marked

nodes– Removing a node doesn’t slow down

other method calls …

• Must still lock pred and curr nodes.

Art of Multiprocessor Programming© Herlihy-Shavit 2007 10

Validation

• No need to rescan list!• Check that pred is not marked• Check that curr is not marked• Check that pred points to curr

Art of Multiprocessor Programming© Herlihy-Shavit 2007 11

Business as Usual

a b c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 12

Business as Usual

a b c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 13

Business as Usual

a b c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 14

Business as Usual

a b c

remove(b)

Art of Multiprocessor Programming© Herlihy-Shavit 2007 15

Business as Usual

a b c

a not marked

Art of Multiprocessor Programming© Herlihy-Shavit 2007 16

Business as Usual

a b c

a still points to b

Art of Multiprocessor Programming© Herlihy-Shavit 2007 17

Business as Usual

a b c

Logical

delete

Art of Multiprocessor Programming© Herlihy-Shavit 2007 18

Business as Usual

a b c

physical

delete

Art of Multiprocessor Programming© Herlihy-Shavit 2007 19

Business as Usual

a b c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 20

Invariant

• If not marked then item in the set and reachable from head and if not yet traversed it is reachable from pred

• Marked elements may be reachable or not

Art of Multiprocessor Programming© Herlihy-Shavit 2007 21

New Abstraction Map

• S(head) =– { x | there exists node a such

that•a reachable from head and•a.item = x and•a is unmarked

– }

Art of Multiprocessor Programming© Herlihy-Shavit 2007 22

Validationprivate boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }

Art of Multiprocessor Programming© Herlihy-Shavit 2007 23

private boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }

List Validate Method

Predecessor not logically removed

Art of Multiprocessor Programming© Herlihy-Shavit 2007 24

private boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }

List Validate Method

Current not logically removed

Art of Multiprocessor Programming© Herlihy-Shavit 2007 25

private boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }

List Validate Method

Predecessor stillpoints to current

Art of Multiprocessor Programming© Herlihy-Shavit 2007 26

Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {

pred.unlock();curr.unlock();

}

Art of Multiprocessor Programming© Herlihy-Shavit 2007 27

Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {

pred.unlock();curr.unlock();

}

Validate as before

Art of Multiprocessor Programming© Herlihy-Shavit 2007 28

Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {

pred.unlock();curr.unlock();

}

Key found

Art of Multiprocessor Programming© Herlihy-Shavit 2007 29

Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {

pred.unlock();curr.unlock();

}

Logical remove

Art of Multiprocessor Programming© Herlihy-Shavit 2007 30

Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {

pred.unlock();curr.unlock();

}

Physical remove

Art of Multiprocessor Programming© Herlihy-Shavit 2007 31

Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}

Art of Multiprocessor Programming© Herlihy-Shavit 2007 32

Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}

Start at the head

Art of Multiprocessor Programming© Herlihy-Shavit 2007 33

Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}

Search key range

Art of Multiprocessor Programming© Herlihy-Shavit 2007 34

Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}

Traverse without locking(nodes may have been

removed)

Art of Multiprocessor Programming© Herlihy-Shavit 2007 35

Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}

Present and undeleted?

Art of Multiprocessor Programming© Herlihy-Shavit 2007 36

Summary: Wait-free Contains

a 0 0 0a b c 0e1d

Use Mark bit + Fact that List is ordered 1. Not marked in the set2. Marked or missing not in the set

Art of Multiprocessor Programming© Herlihy-Shavit 2007 37

Lazy List: summary

a 0 0 0a b c 0e1d

Wait-free contains()

Blocking add() and remove(): possible starvation (if validate fails repeatedly)

Art of Multiprocessor Programming© Herlihy-Shavit 2007 38

Linearizability

• Add and remove use locks: linearization points chosen as usual (successful remove linearized when mark bit set to 1)

• Contains does not use locks: pay attention to unsuccessful calls. Earlier of:• Point where a removed matching node,

or a node with larger key is found• Point before a new matching node is

added to the list

Art of Multiprocessor Programming© Herlihy-Shavit 2007 39

Evaluation• Good:

– contains() doesn’t lock– In fact, it is wait-free! – Good because typically high % contains()– Uncontended calls don’t re-traverse

• Bad– Contended calls do re-traverse– Traffic jam if one thread delays

Art of Multiprocessor Programming© Herlihy-Shavit 2007 40

Traffic Jam• Any concurrent data structure based on

mutual exclusion has a weakness• If one thread

– Enters critical section– And “eats the big muffin”

• Cache miss, page fault, descheduled …• Software error, …

– Everyone else using that lock is stuck!

Art of Multiprocessor Programming© Herlihy-Shavit 2007 41

Reminder: Lock-Free Data Structures

• No matter what …– Some thread will complete method

call– Even if others halt at malicious times– Weaker than wait-free, yet

• Implies that– You can’t use locks

Art of Multiprocessor Programming© Herlihy-Shavit 2007 42

Lock-free Lists

• Next logical step• Eliminate locking entirely• contains() wait-free and add() and

remove() lock-free• Use only compareAndSet()• What could go wrong?

Art of Multiprocessor Programming© Herlihy-Shavit 2007 43

Adding a Node

a c d

Art of Multiprocessor Programming© Herlihy-Shavit 2007 44

Adding a Node

a c d

b

Art of Multiprocessor Programming© Herlihy-Shavit 2007 45

Adding a Node

a c d

b

CAS

Art of Multiprocessor Programming© Herlihy-Shavit 2007 47

Adding a Node

a c d

b

Art of Multiprocessor Programming© Herlihy-Shavit 2007 48

Removing a Node

a b c d

remove b

remove c

CAS CAS

Art of Multiprocessor Programming© Herlihy-Shavit 2007 49

Bad news

Look Familiar?

a b c d

remove b

remove c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 50

Problem

• Method updates node’s next field after node has been removed

Art of Multiprocessor Programming© Herlihy-Shavit 2007 51

Solution• Use AtomicMarkableReference• Atomically

– Swing reference and– Update flag

• Remove in two steps– Set mark bit in next field– Redirect predecessor’s pointer

Art of Multiprocessor Programming© Herlihy-Shavit 2007 52

Marking a Node

• AtomicMarkableReference class– Java.util.concurrent.atomic package

address F

mark bit

Reference

Art of Multiprocessor Programming© Herlihy-Shavit 2007 53

Extracting Reference & Mark

Public Object get(boolean[] marked);

Art of Multiprocessor Programming© Herlihy-Shavit 2007 54

Public Object get(boolean[] marked);

Returns reference

Returns mark at array index

0!

Extracting Reference & Mark

Art of Multiprocessor Programming© Herlihy-Shavit 2007 55

Extracting Reference Only

public boolean isMarked();

Value of mark

Art of Multiprocessor Programming© Herlihy-Shavit 2007 56

Changing State

Public boolean compareAndSet( Object expectedRef, Object updateRef, boolean expectedMark, boolean updateMark);

Art of Multiprocessor Programming© Herlihy-Shavit 2007 57

Changing State

Public boolean compareAndSet( Object expectedRef, Object updateRef, boolean expectedMark, boolean updateMark);

If this is the current reference

And this is the current mark …

Art of Multiprocessor Programming© Herlihy-Shavit 2007 58

Changing State

Public boolean compareAndSet( Object expectedRef, Object updateRef, boolean expectedMark, boolean updateMark);

…then change to this new reference …

… and this new mark

Art of Multiprocessor Programming© Herlihy-Shavit 2007 59

Changing State

public boolean attemptMark( Object expectedRef, boolean updateMark);

Art of Multiprocessor Programming© Herlihy-Shavit 2007 60

Changing State

public boolean attemptMark( Object expectedRef, boolean updateMark);

If this is the current reference …

Art of Multiprocessor Programming© Herlihy-Shavit 2007 61

Changing State

public boolean attemptMark( Object expectedRef, boolean updateMark);

.. then change to this new mark.

Art of Multiprocessor Programming© Herlihy-Shavit 2007 62

Removing a Node

a b c d

remove c

CAS

Art of Multiprocessor Programming© Herlihy-Shavit 2007 63

Removing a Node

a b d

remove b

remove c

cCASCAS

failed

Art of Multiprocessor Programming© Herlihy-Shavit 2007 64

Removing a Node

a b d

remove b

remove c

c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 65

Removing a Node

a d

remove b

remove c

Art of Multiprocessor Programming© Herlihy-Shavit 2007 66

Traversing the List

• Q: what do you do when you find a “logically” deleted node in your path?

• A: finish the job.– CAS the predecessor’s next field– Proceed (repeat as needed)

Art of Multiprocessor Programming© Herlihy-Shavit 2007 67

Lock-Free Traversal

a b c dCAS

Uh-oh

Art of Multiprocessor Programming© Herlihy-Shavit 2007 68

The Window Class

class Window { public Node pred; public Node curr; Window(Node pred, Node curr) { this.pred = pred; this.curr = curr; }}

Art of Multiprocessor Programming© Herlihy-Shavit 2007 69

The Window Class

class Window { public Node pred; public Node curr; Window(Node pred, Node curr) { this.pred = pred; this.curr = curr; }}

A container for pred and current

values

Art of Multiprocessor Programming© Herlihy-Shavit 2007 70

Using the Find Method

Window window = find(head, key); Node pred = window.pred; curr = window.curr;

Art of Multiprocessor Programming© Herlihy-Shavit 2007 71

Using the Find Method

Window window = find(head, key); Node pred = window.pred; curr = window.curr;

Find returns window

Art of Multiprocessor Programming© Herlihy-Shavit 2007 72

Using the Find Method

Window window = find(head, key); Node pred = window.pred; curr = window.curr;

Extract pred and curr

Art of Multiprocessor Programming© Herlihy-Shavit 2007 75

Lock-free Findpublic Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Art of Multiprocessor Programming© Herlihy-Shavit 2007 76

Lock-free Findpublic Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

If list changes

while traversed, start over.Lock-Free

because we start over

only if someone

else makes progress

Art of Multiprocessor Programming© Herlihy-Shavit 2007 77

public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Lock-free Find

Start looking from head

Art of Multiprocessor Programming© Herlihy-Shavit 2007 78

public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Lock-free Find

Move down the list

Art of Multiprocessor Programming© Herlihy-Shavit 2007 79

public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Lock-free Find

Get ref to successor and mark bit of current node

Art of Multiprocessor Programming© Herlihy-Shavit 2007 80

public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Lock-free Find

Try to remove marked nodes in path… code

details soon

Art of Multiprocessor Programming© Herlihy-Shavit 2007 81

public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Lock-free Find

If curr key is greater or equal, return pred and curr

Art of Multiprocessor Programming© Herlihy-Shavit 2007 82

public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}

Lock-free Find

Otherwise advance window and loop again

Art of Multiprocessor Programming© Herlihy-Shavit 2007 83

Lock-free Find

retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…

Art of Multiprocessor Programming© Herlihy-Shavit 2007 84

Lock-free Find

retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…

Try to snip out node

Art of Multiprocessor Programming© Herlihy-Shavit 2007 85

Lock-free Find

retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…

If predecessor’s next field changed must

retry whole traversal

Art of Multiprocessor Programming© Herlihy-Shavit 2007 86

Lock-free Find

retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…

Otherwise move on to check if next node

deleted

Art of Multiprocessor Programming© Herlihy-Shavit 2007 87

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

Art of Multiprocessor Programming© Herlihy-Shavit 2007 88

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

Keep trying

Art of Multiprocessor Programming© Herlihy-Shavit 2007 89

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

Find neighbors

Art of Multiprocessor Programming© Herlihy-Shavit 2007 90

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

Key is not there …

Art of Multiprocessor Programming© Herlihy-Shavit 2007 91

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

Try to mark node as deleted

Art of Multiprocessor Programming© Herlihy-Shavit 2007 92

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

If it doesn’t work, just retry. If it does, job

essentially done

Art of Multiprocessor Programming© Herlihy-Shavit 2007 93

Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}

Try to advance reference(if we don’t succeed, someone else did or will).

a

Art of Multiprocessor Programming© Herlihy-Shavit 2007 94

Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}}

Art of Multiprocessor Programming© Herlihy-Shavit 2007 95

Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}} Item already there

Art of Multiprocessor Programming© Herlihy-Shavit 2007 96

Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}}

create new node

Art of Multiprocessor Programming© Herlihy-Shavit 2007 97

Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}}

Install new node, else retry loop

Art of Multiprocessor Programming© Herlihy-Shavit 2007 98

Wait-free Contains

public boolean contains(T item) { boolean marked; int key = item.hashCode(); Node curr = this.head; while (curr.key < key) curr = curr.next; Node succ = curr.next.get(marked); return (curr.key == key && !marked[0]) }

Art of Multiprocessor Programming© Herlihy-Shavit 2007 99

Wait-free Contains

public boolean contains(T item) { boolean marked; int key = item.hashCode(); Node curr = this.head; while (curr.key < key) curr = curr.next; Node succ = curr.next.get(marked); return (curr.key == key && !marked[0]) }

Only diff is that we use method get and check array marked

Art of Multiprocessor Programming© Herlihy-Shavit 2007 100

Summary: Lock-free Removal

a 0 0 0a b c 0e1c

Logical Removal =Set Mark Bit

PhysicalRemovalCAS pointer

Use CAS to verify pointer is correct

Not enough!

Art of Multiprocessor Programming© Herlihy-Shavit 2007 101

Lock-free Removal

a 0 0 0a b c 0e1c

Logical Removal =Set Mark Bit

PhysicalRemovalCAS

0dProblem: d not added to list…Must Prevent manipulation of removed node’s pointer

Node added BeforePhysical Removal CAS

Art of Multiprocessor Programming© Herlihy-Shavit 2007 102

Our Solution: Combine Bit and Pointer

a 0 0 0a b c 0e1c

Logical Removal =Set Mark Bit

PhysicalRemovalCAS

0d

Mark-Bit and Pointerare CASed together

Fail CAS: Node not added after logical Removal

Art of Multiprocessor Programming© Herlihy-Shavit 2007 103

A Lock-free Algorithm

a 0 0 0a b c 0e1c

1. Lock-free add() and remove() physically remove marked nodes

2. Wait-free find() traverses both marked and removed nodes

Art of Multiprocessor Programming© Herlihy-Shavit 2007 104

Performance

On 16 node shared memory machineBenchmark throughput of Java List-based Setalgs. Vary % of Contains() method Calls.

Art of Multiprocessor Programming© Herlihy-Shavit 2007 105

High Contains Ratio

Lock-free Lazy list

Course GrainedFine Lock-coupling

Art of Multiprocessor Programming© Herlihy-Shavit 2007 106

Low Contains Ratio

Lock-free

Lazy list

Course GrainedFine Lock-coupling

Art of Multiprocessor Programming© Herlihy-Shavit 2007 107

As Contains Ratio Increases

Lock-free

Lazy list

Course GrainedFine Lock-coupling

% Contains()

Art of Multiprocessor Programming© Herlihy-Shavit 2007 108

Summary

• Coarse-grained locking• Fine-grained locking• Optimistic synchronization• Lazy synchronization• Lock-free synchronization

Art of Multiprocessor Programming© Herlihy-Shavit 2007 109

“To Lock or Not to Lock”

• Locking vs. Non-blocking: Extremist views on both sides

• The answer: nobler to compromise, combine locking and non-blocking– Example: Lazy list combines blocking

add() and remove() and a wait-free contains()

– Blocking/non-blocking is a property of a method

Art of Multiprocessor Programming© Herlihy-Shavit 2007 110

         This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.

• You are free:– to Share — to copy, distribute and transmit the work – to Remix — to adapt the work

• Under the following conditions:– Attribution. You must attribute the work to “The Art of

Multiprocessor Programming” (but not in any way that suggests that the authors endorse you or your use of the work).

– Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.

• For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to– http://creativecommons.org/licenses/by-sa/3.0/.

• Any of the above conditions can be waived if you get permission from the copyright holder.

• Nothing in this license impairs or restricts the author's moral rights.

top related