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

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

Dec 16, 2015

Download

Documents

Sullivan Ryles
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Linked Lists: Lazy and Non-Blocking Synchronization Based on the companion slides for The Art of Multiprocessor Programming (Maurice Herlihy & Nir Shavit)

Linked Lists: Lazy and Non-Blocking Synchronization

Based on the companion slides forThe Art of Multiprocessor

Programming(Maurice Herlihy & Nir Shavit)

Page 2: Linked Lists: Lazy and Non-Blocking Synchronization Based on the companion slides for The 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”

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

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)

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 4

Lazy Removal

aa b c d

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 5

Lazy Removal

aa b c d

Present in list

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 6

Lazy Removal

aa b c d

Logically deleted

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 7

Lazy Removal

aa b c d

Physically deleted

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 8

Lazy Removal

aa b d

Physically deleted

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

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.

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

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

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 11

Business as Usual

a b c

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 12

Business as Usual

a b c

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 13

Business as Usual

a b c

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 14

Business as Usual

a b c

remove(b)

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 15

Business as Usual

a b c

a not marked

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 16

Business as Usual

a b c

a still points to b

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 17

Business as Usual

a b c

Logical

delete

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 18

Business as Usual

a b c

physical

delete

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 19

Business as Usual

a b c

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

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

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

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

– }

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 22

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

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

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

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

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

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

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

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

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();

}

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

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

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

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

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

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

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

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

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

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;}

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

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

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

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

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

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)

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

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?

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

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

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

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)

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

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

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

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

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

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!

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

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

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

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?

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 43

Adding a Node

a c d

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 44

Adding a Node

a c d

b

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 45

Adding a Node

a c d

b

CAS

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 47

Adding a Node

a c d

b

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 48

Removing a Node

a b c d

remove b

remove c

CAS CAS

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 49

Bad news

Look Familiar?

a b c d

remove b

remove c

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 50

Problem

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

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

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

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 52

Marking a Node

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

address F

mark bit

Reference

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 53

Extracting Reference & Mark

Public Object get(boolean[] marked);

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 54

Public Object get(boolean[] marked);

Returns reference

Returns mark at array index

0!

Extracting Reference & Mark

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 55

Extracting Reference Only

public boolean isMarked();

Value of mark

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 56

Changing State

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

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

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 …

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

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

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 59

Changing State

public boolean attemptMark( Object expectedRef, boolean updateMark);

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 60

Changing State

public boolean attemptMark( Object expectedRef, boolean updateMark);

If this is the current reference …

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 61

Changing State

public boolean attemptMark( Object expectedRef, boolean updateMark);

.. then change to this new mark.

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 62

Removing a Node

a b c d

remove c

CAS

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 63

Removing a Node

a b d

remove b

remove c

cCASCAS

failed

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 64

Removing a Node

a b d

remove b

remove c

c

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 65

Removing a Node

a d

remove b

remove c

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

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)

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 67

Lock-Free Traversal

a b c dCAS

Uh-oh

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

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; }}

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

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

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 70

Using the Find Method

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

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

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

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

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

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

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; }}}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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); }…

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

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

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

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

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

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

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

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;}}}

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

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

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

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

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

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 …

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

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

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

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

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

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

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

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;}}}

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

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

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

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

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

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

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

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]) }

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

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

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

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!

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

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

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

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

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

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

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

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.

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 105

High Contains Ratio

Lock-free Lazy list

Course GrainedFine Lock-coupling

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 106

Low Contains Ratio

Lock-free

Lazy list

Course GrainedFine Lock-coupling

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 107

As Contains Ratio Increases

Lock-free

Lazy list

Course GrainedFine Lock-coupling

% Contains()

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

Art of Multiprocessor Programming© Herlihy-Shavit 2007 108

Summary

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

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

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

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

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.