Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

254
Linked Lists: Locking, Lock- Free, and Beyond The Art of Multiprocessor Programming Spring 2007

Transcript of Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

Page 1: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

Linked Lists: Locking, Lock-Free,

and Beyond …The Art of

Multiprocessor Programming

Spring 2007

Page 2: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 2

Last Lecture: Spin-Locks

CS

Resets lock upon exit

spin lock

critical section

...

Page 3: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 3

Today: Concurrent Objects

• AddingThreads • Should not lower throughput

– Contention effects– Mostly fixed by Queue locks

• Should increase throughput– Not possible if inherently sequential– Surprising things are parallelizable

Page 4: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 4

Coarse-Grained Synchronization

• Each method locks the object– Avoid contention using queue locks – Easy to reason about

• In simple cases

– Standard Java model• Synchronized blocks and methods

• So, are we done?

Page 5: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 5

Coarse-Grained Synchronization

• Sequential bottleneck– All threads “stand in line”

• Adding more threads– Does not improve throughput– Struggle to keep it from getting worse

• So why even use a multiprocessor?– Well, some apps inherently parallel …

Page 6: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 6

This Lecture

• Introduce four “patterns”– Bag of tricks …– Methods that work more than once …

• For highly-concurrent objects• Goal:

– Concurrent access– More threads, more throughput

Page 7: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 7

First:Fine-Grained Synchronization• Instead of using a single lock ..• Split object into

– Independently-synchronized components

• Methods conflict when they access– The same component …– At the same time

Page 8: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 8

Second:Optimistic Synchronization

• Object = linked set of components• Search without locking …• If you find it, lock and check …

– OK, we are done– Oops, try again

• Evaluation– cheaper than locking– mistakes are expensive

Page 9: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 9

Third:Lazy Synchronization

• Postpone hard work• Removing components is tricky

– Logical removal• Mark component to be deleted

– Physical removal• Do what needs to be done

Page 10: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 10

Fourth:Lock-Free Synchronization

• Don’t use locks at all– Use compareAndSet() & relatives …

• Advantages– Robust against asynchrony

• Disadvantages– Complex– Sometimes high overhead

Page 11: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 11

Linked List

• Illustrate these patterns …• Using a list-based Set

– Common application– Building block for other apps

Page 12: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 12

The Evolution of Concurrent List-based Sets

Course Grained

Fine Lock-Coupling

Course Optimistic

FineOptim-istic

Lock-freeLazy

FineOptim-istic

Page 13: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 13

Set Interface

• Unordered collection of objects• No duplicates• Methods

– Add() a new object– Remove() an object– Test if set Contains() object

Page 14: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 14

List-Based Sets

public interface Set { public boolean add(Object x); public boolean remove(Object x); public boolean contains(Object x);}

Page 15: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 15

List-Based Sets

public interface Set { public boolean add(Object x); public boolean remove(Object x); public boolean contains(Object x);}

Add object to set

Page 16: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 16

List-Based Sets

public interface Set { public boolean add(Object x); public boolean remove(Object x); public boolean contains(Object x);}

Remove object from set

Page 17: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 17

List-Based Sets

public interface Set { public boolean add(Object x); public boolean remove(Object x); public boolean contains(Object x);}

Is object in set?

Page 18: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 18

List Node

public class Node { public Object object; public int key; public Node next;}

Page 19: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 19

List Node

public class Node { public Object object; public int key; public Node next;}

Object of interest

Page 20: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 20

List Node

public class Node { public Object object; public int key; public Node next;}

Usually hash code

Page 21: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 21

List Node

public class Node { public Object object; public int key; public Node next;}

Reference to next node

Page 22: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 22

The List-Based Set

a b c

Ordered + Sentinel nodes(min & max possible keys)

Page 23: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 23

Reasoning about Concurrent Objects

• Invariant– Property that always holds

• Established by– True when object is created– Truth preserved by each method

• Each step of each method

Page 24: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 24

Specifically …

• Invariants preserved by– add()– remove()– contains()

• Most steps are trivial– Usually one step tricky– Often linearization point

Page 25: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 25

Interference

• Proof that invariants preserved works only if– methods considered– are the only modifiers

• Language encapsulation helps– List nodes not visible outside class

Page 26: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 26

Interference

• Freedom from interference neeeded even for removed nodes– Some algorithms traverse removed

nodes– Careful with malloc() & free()!

• Garbage-collection helps here

Page 27: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 27

Abstract Data Types

• Concrete representation

• Abstract Type– {a, b}

a b

Page 28: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 28

Abstract Data Types

• Meaning of rep given by abstraction map

– S( ) = {a,b}a b

Page 29: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 29

Rep Invariant

• Which concrete values are meaningful?– Sorted? Duplicates?

• Rep invariant– Characterizes legal concrete reps– Preserved by methods– Relied on by methods

Page 30: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 30

Blame Game

• Rep invariant is a contract• Suppose– add() leaves behind 2 copies of x– remove() removes only 1

• Which one is incorrect?

Page 31: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 31

Blame Game

• Suppose– add() leaves behind 2 copies of x– remove() removes only 1

• Which one is incorrect?– If rep invariant says no duplicates• add() is incorrect

– Otherwise• remove() is incorrect

Page 32: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 32

Rep Invariant (partly)

• Sentinel nodes– tail reachable from head

• Sorted, no duplicates

Page 33: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 33

Abstraction Map

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

•A reachable from head and•a.object = x

– }

Page 34: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 34

Sequential List Based Set

a c d

b

a b c

Add()

Remove()

Page 35: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 35

Course Grained Locking

a b d

c

Simple but hotspot + bottleneck

Page 36: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 36

Coarse-Grained Locking

• Easy, same as synchronized methods

– “One lock to rule them all …”

• Simple, clearly correct– Deserves respect!

• Works poorly with contention– Queue locks help– But bottleneck still an issue

Page 37: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 37

Fine-grained Locking

• Requires careful thought– “Do not meddle in the affairs of

wizards, for they are subtle and quick to anger”

• Split object into pieces– Each piece has own lock– Methods that work on disjoint pieces

need not exclude each other

Page 38: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 38

Hand-over-Hand locking

a b c

Page 39: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 39

Hand-over-Hand locking

a b c

Page 40: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 40

Hand-over-Hand locking

a b c

Page 41: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 41

Hand-over-Hand locking

a b c

Page 42: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 42

Hand-over-Hand locking

a b c

Page 43: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 43

Removing a Node

a b c d

remove b

Page 44: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 44

Removing a Node

a b c d

remove b

Page 45: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 45

Removing a Node

a b c d

remove b

Page 46: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 46

Removing a Node

a b c d

remove b

Page 47: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 47

Removing a Node

a c d

remove b

Page 48: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 48

Removing a Node

a b c d

remove b

remove c

Page 49: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 49

Removing a Node

a b c d

remove b

remove c

Page 50: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 50

Removing a Node

a b c d

remove b

remove c

Page 51: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 51

Removing a Node

a b c d

remove b

remove c

Page 52: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 52

Removing a Node

a b c d

remove b

remove c

Page 53: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 53

Removing a Node

a b c d

remove b

remove c

Page 54: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 54

Removing a Node

a b c d

remove b

remove c

Page 55: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 55

Removing a Node

a b c d

remove b

remove c

Page 56: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 56

Removing a Node

a b c d

remove b

remove c

Page 57: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 57

Uh, Oh

a c d

remove b

remove c

Still in list

Page 58: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 58

Problem

• To delete node b– Swing node a’s next field to c

• Problem is,– Someone could delete c concurrently

ba c

ba c

Page 59: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 59

Insight

• If a node is locked– No one can delete node’s successor

• If a thread locks– Node to be deleted– And its predecessor– Then it works

Page 60: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 60

Hand-Over-Hand Again

a b c d

remove b

Page 61: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 61

Hand-Over-Hand Again

a b c d

remove b

Page 62: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 62

Hand-Over-Hand Again

a b c d

remove b

Page 63: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 63

Hand-Over-Hand Again

a b c d

remove b

Found it!

Page 64: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 64

Hand-Over-Hand Again

a b c d

remove b

Found it!

Page 65: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 65

Hand-Over-Hand Again

a c d

remove b

Found it!

Page 66: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 66

Removing a Node

a b c d

remove b

remove c

Page 67: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 67

Removing a Node

a b c d

remove b

remove c

Page 68: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 68

Removing a Node

a b c d

remove b

remove c

Page 69: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 69

Removing a Node

a b c d

remove b

remove c

Page 70: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 70

Removing a Node

a b c d

remove b

remove c

Page 71: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 71

Removing a Node

a b c d

remove b

remove c

Page 72: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 72

Removing a Node

a b c d

remove b

remove c

Page 73: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 73

Removing a Node

a b d

remove b

remove c

Page 74: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 74

Removing a Node

a b d

remove b

remove c

Page 75: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 75

Removing a Node

a d

remove b

remove c

Page 76: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 76

Remove method

public boolean remove(Object object) { int key = object.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}

Page 77: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 77

Remove method

public boolean remove(Object object) { int key = object.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}

Key used to order node

Page 78: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 78

Remove method

public boolean remove(Object object) { int key = object.hashCode(); Node pred, curr; try { … } finally { currNode.unlock(); predNode.unlock(); }}

Predecessor and current nodes

Page 79: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 79

Remove method

public boolean remove(Object object) { int key = object.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}

Make sure locks

released

Page 80: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 80

Remove method

public boolean remove(Object object) { int key = object.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}

Everything else

Page 81: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 81

Remove method

try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }

Page 82: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 82

Remove method

try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }

lock previous

Page 83: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 83

Remove method

try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }

Lock current

Page 84: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 84

Remove method

try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }

Traversing list

Page 85: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 85

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Page 86: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 86

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Search key range

Page 87: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 87

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

At start of each loop: curr and pred locked

Page 88: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 88

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;If node found, remove

it

Page 89: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 89

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;If node found, remove

it

Page 90: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 90

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Unlock predecessor

Page 91: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 91

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Only one node locked!

Page 92: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 92

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

demote current

Page 93: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 93

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = currNode; curr = curr.next; curr.lock(); } return false;

Find and lock new current

Page 94: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 94

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = currNode; curr = curr.next; curr.lock(); } return false;

Lock invariant restored

Page 95: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 95

Remove: searching

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Otherwise, not present

Page 96: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 97

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Why remove() is linearizable

head ~> predA --> currA

so the object is in the set

Page 97: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 98

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Why remove() is linearizable

Node locked, so no other thread can remove it ….

Page 98: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 99

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Why remove() is linearizable

Linearization point

Page 99: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 100

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Why remove() is linearizable

Object not present

Page 100: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 101

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Why remove() is linearizable

predA --> currA

predA.key < keykey < currA.key

Page 101: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 102

while (curr.key <= key) { if (object == curr.object) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;

Why remove() is linearizable

Linearization point: when currA set to node

with higher key

Page 102: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 103

Adding Nodes

• To add node e– Must lock predecessor– Must lock successor

• Neither can be deleted– (Is successor lock actually required?)

Page 103: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 104

Same Abstraction Map

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

•A reachable from head and•a.object = x

– }

Page 104: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 105

Rep Invariant

• Easy to check that– Tail always reachable from head– Nodes sorted, no duplicates

Page 105: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 106

Drawbacks

• Better than coarse-grained lock– Threads can traverse in parallel

• Still not ideal– Long chain of acquire/release– Inefficient

Page 106: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 107

Optimistic Synchronization

• Find nodes without locking• Lock nodes• Check that everything is OK

Page 107: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 108

Optimistic Fine Grained

b d e

To insert C:• Optimistically traverse

list to find b• Lock b.curr then lock

b.succ• Re-Traverse list to find

b and verify predcurr

• Perform insert and release locks

a

13

32 2

c4

Page 108: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 109

Same Abstraction Map

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

•A reachable from head and•a.object = x

– }

Page 109: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 110

Preserving Invariants

• Not same as before as we traverse deleted elements

• But we establish properties by– Validation– After we lock target nodes

Page 110: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 111

Scanning Deleted Items

a

b d

e

remove e

A

Pred and curr could point to removed nodes

Page 111: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 112

Removing a Node

a b c d

remove c

return true

Page 112: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 113

What Can Go Wrong?

a b c d

remove c

remove b

Page 113: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 114

Check that Node is Still Accessible

a b c d

remove c

Page 114: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 115

What Can Go Wrong?

a b c d

remove c

Add b’

b’

Page 115: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 116

What Can Go Wrong?

a b c d

remove c

b’

Page 116: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 117

Check that Nodes Still Adjacent

a b c d

remove c

Page 117: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 118

Correctness

• If– Nodes b and c both locked– Node b still accessible– Node c still successor to b

• Then– Neither will be deleted– OK to delete and return true

Page 118: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 119

Removing an Absent Node

a b d e

remove c

return false

Page 119: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 120

Correctness

• If– Nodes b and d both locked– Node b still accessible– Node d still successor to b

• Then– Neither will be deleted– No thread can add c after b– OK to return false

Page 120: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 121

Validationprivate boolean validate(Node pred, Node curry) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Page 121: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 122

private boolean validate(Node pred, Node curr) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Validation

Predecessor & current

nodes

Page 122: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 123

private boolean validate(Node pred, Node curr) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Validation

Start at the beginning

Page 123: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 124

private boolean validate(Node pred, Node curr) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Validation

Search range of keys

Page 124: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 125

private boolean validate(Node pred, Node curr) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Validation

Predecessor reachable

Page 125: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 126

private boolean validate(Node pred, Node curry) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Validation

Is current node next?

Page 126: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 127

private boolean validate(Node pred, Node curr) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

Validation

Otherwise move on

Page 127: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 128

private boolean validate(Node pred, Node curr) { Node node = head; while (node.key <= pred.key) { if (node == pred) return pred.next == curr; node = node.next; } return false;}

ValidationPredecessor not

reachable

Page 128: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 129

Remove: searchingpublic boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Page 129: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 130

public boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Remove: searching

Search key

Page 130: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 131

public boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Remove: searching

Retry on synchronization conflict

Page 131: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 132

public boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Remove: searching

Examine predecessor and current nodes

Page 132: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 133

public boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Remove: searching

Search by key

Page 133: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 134

public boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Remove: searching

Stop if we find object

Page 134: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 135

public boolean remove(Object object) { int key = object.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (object == curr.object) break; pred = curr; curr = curr.next; } …

Remove: searching

Move along

Page 135: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 136

On Exit from Loop

• If object is present– curr holds object– pred just before curr

• If object is absent– curr has first higher key– pred just before curr

• Assuming no synchronization problems

Page 136: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 137

Remove Methodtry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.object == object) { pred.next = curr.next; return true; } else { return false; }}} finally {

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

}}}

Page 137: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 138

try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.object == object) { pred.next = curr.next; return true; } else { return false; }}} finally {

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

}}}

Remove Method

Always unlock

Page 138: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 139

try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.object == object) { pred.next = curr.next; return true; } else { return false; }}} finally {

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

}}}

Remove Method

Lock both nodes

Page 139: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 140

try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.object == object) { pred.next = curr.next; return true; } else { return false; }}} finally {

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

}}}

Remove Method

Check for synchronization

conflicts

Page 140: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 141

try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.object == object) { pred.next = curr.next; return true; } else { return false; }}} finally {

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

}}}

Remove Method

Object found, remove node

Page 141: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 142

try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.object == object) { pred.next = curr.next; return true; } else { return false; }}} finally {

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

}}}

Remove Method

Object not found

Page 142: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 143

Summary: Wait-free Traversals

b c da

1. Traverse removed nodes2. Must have non-interference3. Natural in GC languages like

Java™

Reachable =in the set

Page 143: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 144

Summary Optimistic List

b c ea

1. Limited Hotspots (Only at locked Add(), Remove(), Find() destination locations, not traversals)

2. But two traversals3. Yet traversals are wait-free!

Page 144: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 145

So Far, So Good

• Much less lock acquisition/release– Performance– Concurrency

• Problems– Need to traverse list twice– contains() method acquires locks

• Most common method call

Page 145: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 146

Evaluation

• Optimistic works if– cost of scanning twice without locks

<– cost of Scanning once with locks

• Drawback– Contains() acquires locks– 90% of calls in many apps

Page 146: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 147

Lazy List

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

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

Page 147: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 148

Lazy List

• Remove Method– 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 148: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 149

Lazy Removal

a 0 0 0a b c 0d1c

Logical Removal =Set Mark Bit

PhysicalRemova

l

Add a separate mark bit field to each node: 1. mark node as deleted 2. redirect pointer

Page 149: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 150

Lazy Removal

a 0 0 0a b c 0d

1 32 2

1c

4

LogicalRemova

l

PhysicalRemova

l

ReleaseLocks

1. Optimistically traverse list to find b

2. Lock b.curr then lock b.succ

3. verify predcurr4. Perform logical then

physical removal5. Release locks

Page 150: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 151

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 151: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 152

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 152: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 153

Business as Usual

a b c d

Page 153: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 154

Business as Usual

a b c d

Page 154: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 155

Business as Usual

a b c d

Page 155: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 156

Business as Usual

a b c d

Page 156: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 157

Business as Usual

a b c d

Page 157: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 158

Interference

a b c d

Page 158: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 159

Interference

a b c d

Page 159: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 160

Interference

a b c d

Page 160: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 161

Interference

a b c d

Remove c

Page 161: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 162

Validation

a b c d

b not marke

d

Page 162: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 163

Interference

a b c d

c not marke

d

Page 163: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 164

Interference

a b c d

b still points

to c

Page 164: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 165

Logical Delete

a b c d

mark

Page 165: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 166

Scan Through

a b c d

So what

?

Remove c

Page 166: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 167

Physical Deletion

a b c d

So what

?

Remove c

Page 167: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 168

New Abstraction Map

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

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

– }

Page 168: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 169

Invariant

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

reachable from pred

Page 169: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 170

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

Page 170: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 171

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

List Validate Method

Predecessor not Logically removed

Page 171: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 172

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

List Validate Method

Current not Logically removed

Page 172: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 173

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

List Validate Method

Predecessor stillPoints to current

Page 173: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 174

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 174: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 175

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 175: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 176

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 176: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 177

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 177: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 178

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 178: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 179

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

Page 179: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 180

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

Start at the head

Page 180: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 181

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

Search key range

Page 181: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 182

Containspublic boolean contains(Object object) { int key = object.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 182: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 183

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

Present and undeleted?

Page 183: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 184

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 184: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 185

Lazy List

a 0 0 0a b c 0e1d

Lazy Add() and Remove() + Wait-free Contains()

Page 185: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 186

Evaluation

• Good:– Contains method doesn’t need to lock– In fact, its 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 186: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 187

Traffic Jam

• Any concurrent data structure based on mutual exclusion has a weakness

• If one thread– Enters critical section– And “eats the big muffin” (stops running)

• Cache miss, page fault, descheduled …

– Everyone else using that lock is stuck!

Page 187: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 188

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– Um, that’s why they call it lock-free

Page 188: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 189

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 189: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 190

Adding a Node

a b c

Page 190: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 191

Adding a Node

a b c

b

Page 191: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 192

Adding a Node

a b c

b

CAS

Page 192: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 193

Adding a Node

a b c

b

Page 193: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 194

Adding a Node

a b c

b

Page 194: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 195

Removing a Node

a b c d

remove b

remove c

CAS CAS

Page 195: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 196

Look Familiar?

a b c d

remove b

remove c

Still in list

Page 196: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 197

Problem

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

Page 197: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 198

Solution

• Use AtomicMarkableReference• Atomically

– Swing reference and– Update flag

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

Page 198: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 199

Marking a Node

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

address F

mark bit

Reference

Page 199: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 200

Extracting Reference & Mark

Public T get(boolean[] marked);

Page 200: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 201

Extracting Reference & Mark

Public T get(boolean[] marked);

Returns reference to object of type T

Returns mark at array index

0!

Page 201: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 202

Changing State

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

Page 202: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 203

Changing State

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

If this is the current reference

And this is the current mark …

Page 203: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 204

Changing State

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

…then change to this new reference …

… and this new mark

Page 204: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 205

Changing State

public boolean attemptMark( T expectedRef, boolean updateMark);

Page 205: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 206

Changing State

public boolean attemptMark( T expectedRef, boolean updateMark);

If this is the current reference …

Page 206: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 207

Changing State

public boolean attemptMark( T expectedRef, boolean updateMark);

.. then change to this new mark.

Page 207: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 208

Removing a Node

a b c d

remove c

CAS

Page 208: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 209

Removing a Node

a b d

remove b

remove c

cCASCAS

failed

Page 209: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 210

Removing a Node

a b d

remove b

remove c

c

Page 210: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 211

Removing a Node

a d

remove b

remove c

Page 211: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 212

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 212: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 213

Lock-Free Traversal

a b c dCAS

Uh-oh

Page 213: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 214

The Window Class

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

Page 214: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 215

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 215: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 216

Using the Find Method

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

Page 216: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 217

Using the Find Method

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

Find returns window

Page 217: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 218

Using the Find Method

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

Extract pred and curr

Page 218: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 219

The Find Method

Window window = find(head, key);

At some instant,

pred curr succ

objector …

Page 219: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 220

The Find Method

Window window = find(head,key);

At some instant,

predcurr= succ

succ

object not in list

Page 220: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 221

Removepublic boolean remove(T object) {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 221: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 222

Removepublic boolean remove(T object) {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 222: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 223

Removepublic boolean remove(T object) {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 223: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 224

Removepublic boolean remove(T object) {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;}}} She’s not there …

Page 224: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 225

Removepublic boolean remove(T object) {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 225: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 226

Removepublic boolean remove(T object) {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 226: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 227

Removepublic boolean remove(T object) {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 227: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 228

Addpublic boolean add(T object) { 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(object); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) {return true;}}}}

Page 228: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 229

Addpublic boolean add(T object) { 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(object); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) {return true;}}}} Object already there.

Page 229: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 230

Addpublic boolean add(T object) { 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(object); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) {return true;}}}}

create new node

Page 230: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 231

Addpublic boolean add(T object) { 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(object); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) {return true}}}}

Install new node, else retry loop

Page 231: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 232

Wait-free Contains

public boolean contains(T object) { boolean marked; int key = object.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 232: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 233

Wait-free Contains

public boolean contains(T object) { boolean marked; int key = object.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 from lazy list is that

we get and check marked

Page 233: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 234

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 234: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 235

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 overLock-Free

because we start over

only if someone

else makes progress

Page 235: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 236

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 236: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 237

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 237: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 238

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 current deleted bit

Page 238: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 239

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 deleted nodes in path…code details

soon

Page 239: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 240

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 found curr key that is greater or equal, return

pred and curr

Page 240: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 241

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 241: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 242

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 242: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 243

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 243: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 244

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 244: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 245

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 245: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 246

Summary: 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 246: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 247

Summary: Summary: 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 247: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 248

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 248: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 249

A Lock-free Algorithm

a 0 0 0a b c 0e1c

1. Add() and Remove() physically clean up (remove) marked nodes

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

Page 249: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 250

Performance

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

Page 250: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 251

High Contains Ratio

Lock-free Lazy list

Course GrainedFine Lock-coupling

Page 251: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 252

Low Contains Ratio

Lock-free

Lazy list

Course GrainedFine Lock-coupling

Page 252: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 253

As Contains Ratio Increases

Lock-free

Lazy list

Course GrainedFine Lock-coupling

% Contains()

Page 253: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 254

Summary

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

Page 254: Linked Lists: Locking, Lock-Free, and Beyond … The Art of Multiprocessor Programming Spring 2007.

© Herlihy-Shavit 2007 255

“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