Linked Lists: Lazy and Non-Blocking Synchronization
Based on the companion slides forThe Art of Multiprocessor
Programming(Maurice Herlihy & Nir Shavit)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 2
Lazy List
• Like optimistic, except– Scan once– contains(x) never locks …
• Key insight– Removing nodes causes trouble– Do it “lazily”
Art of Multiprocessor Programming© Herlihy-Shavit 2007 3
Lazy List
• remove()– Scans list (as before)– Locks predecessor & current (as before)
• Logical delete– Marks current node as removed (new!)
• Physical delete– Redirects predecessor’s next (as before)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 4
Lazy Removal
aa b c d
Art of Multiprocessor Programming© Herlihy-Shavit 2007 5
Lazy Removal
aa b c d
Present in list
Art of Multiprocessor Programming© Herlihy-Shavit 2007 6
Lazy Removal
aa b c d
Logically deleted
Art of Multiprocessor Programming© Herlihy-Shavit 2007 7
Lazy Removal
aa b c d
Physically deleted
Art of Multiprocessor Programming© Herlihy-Shavit 2007 8
Lazy Removal
aa b d
Physically deleted
Art of Multiprocessor Programming© Herlihy-Shavit 2007 9
Lazy List
• All Methods– Scan through locked and marked
nodes– Removing a node doesn’t slow down
other method calls …
• Must still lock pred and curr nodes.
Art of Multiprocessor Programming© Herlihy-Shavit 2007 10
Validation
• No need to rescan list!• Check that pred is not marked• Check that curr is not marked• Check that pred points to curr
Art of Multiprocessor Programming© Herlihy-Shavit 2007 11
Business as Usual
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 12
Business as Usual
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 13
Business as Usual
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 14
Business as Usual
a b c
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 15
Business as Usual
a b c
a not marked
Art of Multiprocessor Programming© Herlihy-Shavit 2007 16
Business as Usual
a b c
a still points to b
Art of Multiprocessor Programming© Herlihy-Shavit 2007 17
Business as Usual
a b c
Logical
delete
Art of Multiprocessor Programming© Herlihy-Shavit 2007 18
Business as Usual
a b c
physical
delete
Art of Multiprocessor Programming© Herlihy-Shavit 2007 19
Business as Usual
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 20
Invariant
• If not marked then item in the set and reachable from head and if not yet traversed it is reachable from pred
• Marked elements may be reachable or not
Art of Multiprocessor Programming© Herlihy-Shavit 2007 21
New Abstraction Map
• S(head) =– { x | there exists node a such
that•a reachable from head and•a.item = x and•a is unmarked
– }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 22
Validationprivate boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 23
private boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }
List Validate Method
Predecessor not logically removed
Art of Multiprocessor Programming© Herlihy-Shavit 2007 24
private boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }
List Validate Method
Current not logically removed
Art of Multiprocessor Programming© Herlihy-Shavit 2007 25
private boolean validate(Node pred, Node curr) { return !pred.marked && !curr.marked && pred.next == curr); }
List Validate Method
Predecessor stillpoints to current
Art of Multiprocessor Programming© Herlihy-Shavit 2007 26
Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 27
Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Validate as before
Art of Multiprocessor Programming© Herlihy-Shavit 2007 28
Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Key found
Art of Multiprocessor Programming© Herlihy-Shavit 2007 29
Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Logical remove
Art of Multiprocessor Programming© Herlihy-Shavit 2007 30
Removetry { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.key == key) { curr.marked = true; pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Physical remove
Art of Multiprocessor Programming© Herlihy-Shavit 2007 31
Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 32
Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}
Start at the head
Art of Multiprocessor Programming© Herlihy-Shavit 2007 33
Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}
Search key range
Art of Multiprocessor Programming© Herlihy-Shavit 2007 34
Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}
Traverse without locking(nodes may have been
removed)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 35
Containspublic boolean contains(Item item) { int key = item.hashCode(); Node curr = this.head; while (curr.key < key) { curr = curr.next; } return curr.key == key && !curr.marked;}
Present and undeleted?
Art of Multiprocessor Programming© Herlihy-Shavit 2007 36
Summary: Wait-free Contains
a 0 0 0a b c 0e1d
Use Mark bit + Fact that List is ordered 1. Not marked in the set2. Marked or missing not in the set
Art of Multiprocessor Programming© Herlihy-Shavit 2007 37
Lazy List: summary
a 0 0 0a b c 0e1d
Wait-free contains()
Blocking add() and remove(): possible starvation (if validate fails repeatedly)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 38
Linearizability
• Add and remove use locks: linearization points chosen as usual (successful remove linearized when mark bit set to 1)
• Contains does not use locks: pay attention to unsuccessful calls. Earlier of:• Point where a removed matching node,
or a node with larger key is found• Point before a new matching node is
added to the list
Art of Multiprocessor Programming© Herlihy-Shavit 2007 39
Evaluation• Good:
– contains() doesn’t lock– In fact, it is wait-free! – Good because typically high % contains()– Uncontended calls don’t re-traverse
• Bad– Contended calls do re-traverse– Traffic jam if one thread delays
Art of Multiprocessor Programming© Herlihy-Shavit 2007 40
Traffic Jam• Any concurrent data structure based on
mutual exclusion has a weakness• If one thread
– Enters critical section– And “eats the big muffin”
• Cache miss, page fault, descheduled …• Software error, …
– Everyone else using that lock is stuck!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 41
Reminder: Lock-Free Data Structures
• No matter what …– Some thread will complete method
call– Even if others halt at malicious times– Weaker than wait-free, yet
• Implies that– You can’t use locks
Art of Multiprocessor Programming© Herlihy-Shavit 2007 42
Lock-free Lists
• Next logical step• Eliminate locking entirely• contains() wait-free and add() and
remove() lock-free• Use only compareAndSet()• What could go wrong?
Art of Multiprocessor Programming© Herlihy-Shavit 2007 43
Adding a Node
a c d
Art of Multiprocessor Programming© Herlihy-Shavit 2007 44
Adding a Node
a c d
b
Art of Multiprocessor Programming© Herlihy-Shavit 2007 45
Adding a Node
a c d
b
CAS
Art of Multiprocessor Programming© Herlihy-Shavit 2007 47
Adding a Node
a c d
b
Art of Multiprocessor Programming© Herlihy-Shavit 2007 48
Removing a Node
a b c d
remove b
remove c
CAS CAS
Art of Multiprocessor Programming© Herlihy-Shavit 2007 49
Bad news
Look Familiar?
a b c d
remove b
remove c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 50
Problem
• Method updates node’s next field after node has been removed
Art of Multiprocessor Programming© Herlihy-Shavit 2007 51
Solution• Use AtomicMarkableReference• Atomically
– Swing reference and– Update flag
• Remove in two steps– Set mark bit in next field– Redirect predecessor’s pointer
Art of Multiprocessor Programming© Herlihy-Shavit 2007 52
Marking a Node
• AtomicMarkableReference class– Java.util.concurrent.atomic package
address F
mark bit
Reference
Art of Multiprocessor Programming© Herlihy-Shavit 2007 53
Extracting Reference & Mark
Public Object get(boolean[] marked);
Art of Multiprocessor Programming© Herlihy-Shavit 2007 54
Public Object get(boolean[] marked);
Returns reference
Returns mark at array index
0!
Extracting Reference & Mark
Art of Multiprocessor Programming© Herlihy-Shavit 2007 55
Extracting Reference Only
public boolean isMarked();
Value of mark
Art of Multiprocessor Programming© Herlihy-Shavit 2007 56
Changing State
Public boolean compareAndSet( Object expectedRef, Object updateRef, boolean expectedMark, boolean updateMark);
Art of Multiprocessor Programming© Herlihy-Shavit 2007 57
Changing State
Public boolean compareAndSet( Object expectedRef, Object updateRef, boolean expectedMark, boolean updateMark);
If this is the current reference
…
And this is the current mark …
Art of Multiprocessor Programming© Herlihy-Shavit 2007 58
Changing State
Public boolean compareAndSet( Object expectedRef, Object updateRef, boolean expectedMark, boolean updateMark);
…then change to this new reference …
… and this new mark
Art of Multiprocessor Programming© Herlihy-Shavit 2007 59
Changing State
public boolean attemptMark( Object expectedRef, boolean updateMark);
Art of Multiprocessor Programming© Herlihy-Shavit 2007 60
Changing State
public boolean attemptMark( Object expectedRef, boolean updateMark);
If this is the current reference …
Art of Multiprocessor Programming© Herlihy-Shavit 2007 61
Changing State
public boolean attemptMark( Object expectedRef, boolean updateMark);
.. then change to this new mark.
Art of Multiprocessor Programming© Herlihy-Shavit 2007 62
Removing a Node
a b c d
remove c
CAS
Art of Multiprocessor Programming© Herlihy-Shavit 2007 63
Removing a Node
a b d
remove b
remove c
cCASCAS
failed
Art of Multiprocessor Programming© Herlihy-Shavit 2007 64
Removing a Node
a b d
remove b
remove c
c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 65
Removing a Node
a d
remove b
remove c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 66
Traversing the List
• Q: what do you do when you find a “logically” deleted node in your path?
• A: finish the job.– CAS the predecessor’s next field– Proceed (repeat as needed)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 67
Lock-Free Traversal
a b c dCAS
Uh-oh
Art of Multiprocessor Programming© Herlihy-Shavit 2007 68
The Window Class
class Window { public Node pred; public Node curr; Window(Node pred, Node curr) { this.pred = pred; this.curr = curr; }}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 69
The Window Class
class Window { public Node pred; public Node curr; Window(Node pred, Node curr) { this.pred = pred; this.curr = curr; }}
A container for pred and current
values
Art of Multiprocessor Programming© Herlihy-Shavit 2007 70
Using the Find Method
Window window = find(head, key); Node pred = window.pred; curr = window.curr;
Art of Multiprocessor Programming© Herlihy-Shavit 2007 71
Using the Find Method
Window window = find(head, key); Node pred = window.pred; curr = window.curr;
Find returns window
Art of Multiprocessor Programming© Herlihy-Shavit 2007 72
Using the Find Method
Window window = find(head, key); Node pred = window.pred; curr = window.curr;
Extract pred and curr
Art of Multiprocessor Programming© Herlihy-Shavit 2007 75
Lock-free Findpublic Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 76
Lock-free Findpublic Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
If list changes
while traversed, start over.Lock-Free
because we start over
only if someone
else makes progress
Art of Multiprocessor Programming© Herlihy-Shavit 2007 77
public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Lock-free Find
Start looking from head
Art of Multiprocessor Programming© Herlihy-Shavit 2007 78
public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Lock-free Find
Move down the list
Art of Multiprocessor Programming© Herlihy-Shavit 2007 79
public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Lock-free Find
Get ref to successor and mark bit of current node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 80
public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Lock-free Find
Try to remove marked nodes in path… code
details soon
Art of Multiprocessor Programming© Herlihy-Shavit 2007 81
public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Lock-free Find
If curr key is greater or equal, return pred and curr
Art of Multiprocessor Programming© Herlihy-Shavit 2007 82
public Window find(Node head, int key) { Node pred = null, curr = null, succ = null; boolean[] marked = {false}; boolean snip; retry: while (true) { pred = head; curr = pred.next.getReference(); while (true) { succ = curr.next.get(marked); while (marked[0]) { … } if (curr.key >= key) return new Window(pred, curr); pred = curr; curr = succ; }}}
Lock-free Find
Otherwise advance window and loop again
Art of Multiprocessor Programming© Herlihy-Shavit 2007 83
Lock-free Find
retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…
Art of Multiprocessor Programming© Herlihy-Shavit 2007 84
Lock-free Find
retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…
Try to snip out node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 85
Lock-free Find
retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…
If predecessor’s next field changed must
retry whole traversal
Art of Multiprocessor Programming© Herlihy-Shavit 2007 86
Lock-free Find
retry: while (true) { … while (marked[0]) { snip = pred.next.compareAndSet(curr, succ, false, false); if (!snip) continue retry; curr = succ; succ = curr.next.get(marked); }…
Otherwise move on to check if next node
deleted
Art of Multiprocessor Programming© Herlihy-Shavit 2007 87
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 88
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
Keep trying
Art of Multiprocessor Programming© Herlihy-Shavit 2007 89
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
Find neighbors
Art of Multiprocessor Programming© Herlihy-Shavit 2007 90
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
Key is not there …
Art of Multiprocessor Programming© Herlihy-Shavit 2007 91
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
Try to mark node as deleted
Art of Multiprocessor Programming© Herlihy-Shavit 2007 92
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
If it doesn’t work, just retry. If it does, job
essentially done
Art of Multiprocessor Programming© Herlihy-Shavit 2007 93
Removepublic boolean remove(T item) {Boolean snip; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key != key) { return false; } else { Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true;}}}
Try to advance reference(if we don’t succeed, someone else did or will).
a
Art of Multiprocessor Programming© Herlihy-Shavit 2007 94
Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 95
Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}} Item already there
Art of Multiprocessor Programming© Herlihy-Shavit 2007 96
Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}}
create new node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 97
Addpublic boolean add(T item) { boolean splice; while (true) { Window window = find(head, key); Node pred = window.pred, curr = window.curr; if (curr.key == key) { return false; } else { Node node = new Node(item); node.next = new AtomicMarkableRef(curr, false); if (pred.next.compareAndSet(curr, node, false, false)) return true;}}}
Install new node, else retry loop
Art of Multiprocessor Programming© Herlihy-Shavit 2007 98
Wait-free Contains
public boolean contains(T item) { boolean marked; int key = item.hashCode(); Node curr = this.head; while (curr.key < key) curr = curr.next; Node succ = curr.next.get(marked); return (curr.key == key && !marked[0]) }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 99
Wait-free Contains
public boolean contains(T item) { boolean marked; int key = item.hashCode(); Node curr = this.head; while (curr.key < key) curr = curr.next; Node succ = curr.next.get(marked); return (curr.key == key && !marked[0]) }
Only diff is that we use method get and check array marked
Art of Multiprocessor Programming© Herlihy-Shavit 2007 100
Summary: Lock-free Removal
a 0 0 0a b c 0e1c
Logical Removal =Set Mark Bit
PhysicalRemovalCAS pointer
Use CAS to verify pointer is correct
Not enough!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 101
Lock-free Removal
a 0 0 0a b c 0e1c
Logical Removal =Set Mark Bit
PhysicalRemovalCAS
0dProblem: d not added to list…Must Prevent manipulation of removed node’s pointer
Node added BeforePhysical Removal CAS
Art of Multiprocessor Programming© Herlihy-Shavit 2007 102
Our Solution: Combine Bit and Pointer
a 0 0 0a b c 0e1c
Logical Removal =Set Mark Bit
PhysicalRemovalCAS
0d
Mark-Bit and Pointerare CASed together
Fail CAS: Node not added after logical Removal
Art of Multiprocessor Programming© Herlihy-Shavit 2007 103
A Lock-free Algorithm
a 0 0 0a b c 0e1c
1. Lock-free add() and remove() physically remove marked nodes
2. Wait-free find() traverses both marked and removed nodes
Art of Multiprocessor Programming© Herlihy-Shavit 2007 104
Performance
On 16 node shared memory machineBenchmark throughput of Java List-based Setalgs. Vary % of Contains() method Calls.
Art of Multiprocessor Programming© Herlihy-Shavit 2007 105
High Contains Ratio
Lock-free Lazy list
Course GrainedFine Lock-coupling
Art of Multiprocessor Programming© Herlihy-Shavit 2007 106
Low Contains Ratio
Lock-free
Lazy list
Course GrainedFine Lock-coupling
Art of Multiprocessor Programming© Herlihy-Shavit 2007 107
As Contains Ratio Increases
Lock-free
Lazy list
Course GrainedFine Lock-coupling
% Contains()
Art of Multiprocessor Programming© Herlihy-Shavit 2007 108
Summary
• Coarse-grained locking• Fine-grained locking• Optimistic synchronization• Lazy synchronization• Lock-free synchronization
Art of Multiprocessor Programming© Herlihy-Shavit 2007 109
“To Lock or Not to Lock”
• Locking vs. Non-blocking: Extremist views on both sides
• The answer: nobler to compromise, combine locking and non-blocking– Example: Lazy list combines blocking
add() and remove() and a wait-free contains()
– Blocking/non-blocking is a property of a method
Art of Multiprocessor Programming© Herlihy-Shavit 2007 110
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
• You are free:– to Share — to copy, distribute and transmit the work – to Remix — to adapt the work
• Under the following conditions:– Attribution. You must attribute the work to “The Art of
Multiprocessor Programming” (but not in any way that suggests that the authors endorse you or your use of the work).
– Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.
• For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to– http://creativecommons.org/licenses/by-sa/3.0/.
• Any of the above conditions can be waived if you get permission from the copyright holder.
• Nothing in this license impairs or restricts the author's moral rights.