linked lists: locking, lock- free, and beyond … based on the companion slides for the art of...
Post on 30-Mar-2015
223 Views
Preview:
TRANSCRIPT
Linked Lists: Locking, Lock-Free, and Beyond …
Based on the companion slides forThe Art of Multiprocessor
Programming(Maurice Herlihy & Nir Shavit)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 2
Coarse-Grained Synchronization
• Each method locks the object– Easy to reason about
•In simple cases– Standard Java model
•Synchronized blocks and methods• So, are we done?
Art of Multiprocessor Programming© Herlihy-Shavit 2007 3
Coarse-Grained Synchronization
• Sequential bottleneck– Threads “stand in line”
• Adding more threads– Does not improve throughput– Struggle to keep it from getting worse
Art of Multiprocessor Programming© Herlihy-Shavit 2007 4
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 5
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 6
Second:Optimistic Synchronization
• Search without locking …• If you find it, lock and check …
– OK: we are done– Oops: start over
• Evaluation– Usually cheaper than locking– Mistakes are expensive
Art of Multiprocessor Programming© Herlihy-Shavit 2007 7
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 8
Fourth:Lock-Free Synchronization
• Don’t use locks at all– Use compareAndSet() & relatives …
• Advantages– Robust against asynchrony
• Disadvantages– Complex– Sometimes high overhead
Art of Multiprocessor Programming© Herlihy-Shavit 2007 9
Linked List
• Illustrate these patterns …• Using a list-based Set
– Common application– Building block for other apps
Art of Multiprocessor Programming© Herlihy-Shavit 2007 10
Set Interface
• Unordered collection of items• No duplicates• Methods
– add(x) put x in set– remove(x) take x out of set– contains(x) tests if x in set
Art of Multiprocessor Programming© Herlihy-Shavit 2007 11
Set Interface
public interface Set<T> { public boolean add(T x); public boolean remove(T x); public boolean contains(T x);}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 12
Set Interface
public interface Set<T> { public boolean add(T x); public boolean remove(T x); public boolean contains(T x);}
Add item to set
Art of Multiprocessor Programming© Herlihy-Shavit 2007 13
Set Interface
public interface Set<T> { public boolean add(T x); public boolean remove(T x); public boolean contains(Tt x);}
Remove item from set
Art of Multiprocessor Programming© Herlihy-Shavit 2007 14
Set Interface
public interface Set<T> { public boolean add(T x); public boolean remove(T x); public boolean contains(T x);}
Is item in set?
Art of Multiprocessor Programming© Herlihy-Shavit 2007 15
List Node
public class Node { public T item; public int key; public Node next;}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 16
List Node
public class Node { public T item; public int key; public Node next;}
item of interest
Art of Multiprocessor Programming© Herlihy-Shavit 2007 17
List Node
public class Node { public T item; public int key; public Node next;}
Usually hash code
Art of Multiprocessor Programming© Herlihy-Shavit 2007 18
List Node
public class Node { public T item; public int key; public Node next;}
Reference to next node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 19
The List-Based Set
a b c
Sorted with Sentinel nodes(min & max possible keys)
-∞
+∞
Art of Multiprocessor Programming© Herlihy-Shavit 2007 20
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 21
Specifically …
• Invariants preserved by– add()– remove()– contains()
• Most steps are trivial– Usually one step tricky– Often linearization point
Art of Multiprocessor Programming© Herlihy-Shavit 2007 22
Representation Invariants
• Sentinel nodes never added/removed– tail reachable from head
• Elements sorted by key (hash value)
• No duplicates
Art of Multiprocessor Programming© Herlihy-Shavit 2007 23
Interference
• Invariants make sense only if methods considered are the only modifiers
• Language encapsulation helps– List nodes not visible outside class– This guarantees freedom from
interference
Art of Multiprocessor Programming© Herlihy-Shavit 2007 24
Abstract Data Types
• Concrete representation
• Abstract Type– {a, b}
a b
Art of Multiprocessor Programming© Herlihy-Shavit 2007 25
Abstract Data Types
• Meaning of representation given by abstraction map
– S( ) = {a,b}a b
Art of Multiprocessor Programming© Herlihy-Shavit 2007 26
Abstraction Map
• S(head) ={ x | there exists a such that
a reachable from head anda.item = x
}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 27
Sequential List Based Set
a c d
a b c
Add()
Remove()
Art of Multiprocessor Programming© Herlihy-Shavit 2007 28
Sequential List Based Set
a c d
b
a b c
Add()
Remove()
Art of Multiprocessor Programming© Herlihy-Shavit 2007 29
Sequential List Based Set
a c d
b
a b c
Add()
Remove()
Art of Multiprocessor Programming© Herlihy-Shavit 2007 30
Course Grained Locking
a b d
Art of Multiprocessor Programming© Herlihy-Shavit 2007 31
Course Grained Locking
a b d
c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 32
honk!
Course Grained Locking
a b d
c
Simple but hotspot + bottleneck
honk!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 33
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 34
Fine-grained Locking
• Requires careful thought• Split object into pieces
– Each piece has own lock– Methods that work on disjoint pieces
need not exclude each other
• Allows pipelined list traversal
Art of Multiprocessor Programming© Herlihy-Shavit 2007 35
Hand-over-Hand locking
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 36
Hand-over-Hand locking
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 37
Hand-over-Hand locking
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 38
Hand-over-Hand locking
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 39
Hand-over-Hand locking
a b c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 40
Removing a Node
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 41
Removing a Node
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 42
Removing a Node
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 43
Removing a Node
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 44
Removing a Node
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 45
Removing a Node
a c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 46
Removing a Node
a b c d
remove(c)remove(
b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 47
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 48
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 49
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 50
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 51
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 52
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 53
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 54
Uh, Oh
a c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 55
Uh, Oh
a c d
Bad news
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 56
Problem• To delete node b
– Swing node a’s next field to c
• Problem is,– Someone could delete c concurrently
ba c
ba c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 57
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 58
Hand-Over-Hand Again
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 59
Hand-Over-Hand Again
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 60
Hand-Over-Hand Again
a b c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 61
Hand-Over-Hand Again
a b c d
remove(b)
Found it!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 62
Hand-Over-Hand Again
a b c d
remove(b)
Found it!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 63
Hand-Over-Hand Again
a c d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 64
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 65
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 66
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 67
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 68
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 69
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 70
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 71
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 72
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 73
Removing a Node
a b c d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 74
Removing a Node
a b d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 75
Removing a Node
a b d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 76
Removing a Node
a b d
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 77
Removing a Node
a d
remove(b)
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 78
Removing a Node
a d
Art of Multiprocessor Programming© Herlihy-Shavit 2007 79
Remove method
public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 80
Remove method
public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}
Key used to order node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 81
Remove method
public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { currNode.unlock(); predNode.unlock(); }}
Predecessor and current nodes
Art of Multiprocessor Programming© Herlihy-Shavit 2007 82
Remove method
public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}
Make sure locks
released
Art of Multiprocessor Programming© Herlihy-Shavit 2007 83
Remove method
public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}
Everything else
Art of Multiprocessor Programming© Herlihy-Shavit 2007 84
Remove method
try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 85
Remove method
try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }
Lock pred == head
Art of Multiprocessor Programming© Herlihy-Shavit 2007 86
Remove method
try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }
Lock current
Art of Multiprocessor Programming© Herlihy-Shavit 2007 87
Remove method
try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); …} finally { … }
Traversing list
Art of Multiprocessor Programming© Herlihy-Shavit 2007 88
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Art of Multiprocessor Programming© Herlihy-Shavit 2007 89
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Search key range
Art of Multiprocessor Programming© Herlihy-Shavit 2007 90
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { 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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 91
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;If item found, remove
node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 92
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Unlock predecessor
Art of Multiprocessor Programming© Herlihy-Shavit 2007 93
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Only one node locked!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 94
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
demote current
Art of Multiprocessor Programming© Herlihy-Shavit 2007 95
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = currNode; curr = curr.next; curr.lock(); } return false;
Find and lock new current
Art of Multiprocessor Programming© Herlihy-Shavit 2007 96
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = currNode; curr = curr.next; curr.lock(); } return false;
Lock invariant restored
Art of Multiprocessor Programming© Herlihy-Shavit 2007 97
Remove: traversing list
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Otherwise, not present
Art of Multiprocessor Programming© Herlihy-Shavit 2007 98
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Why remove() is linearizable
• pred reachable from head• curr is pred.next• So curr.item is in the set
Art of Multiprocessor Programming© Herlihy-Shavit 2007 99
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Why remove() is linearizable
• pred reachable from head• curr is pred.next• pred.key < key • key < curr.key• So item is not in the set
Art of Multiprocessor Programming© Herlihy-Shavit 2007 100
while (curr.key <= key) { if (item == curr.item) { pred.next = curr.next; return true; } pred.unlock(); pred = curr; curr = curr.next; curr.lock(); } return false;
Why remove() is linearizable
Linearization point
Art of Multiprocessor Programming© Herlihy-Shavit 2007 101
Progress
• To avoid deadlock, locks must be taken by all methods in the same order
• Starvation freedom (if locks are starvation free)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 102
Adding Nodes
• To add a node:– Traverse list using hand-by-hand locking– Lock predecessor– Lock successor
• Neither can be deleted– … and thus item can be inserted inbetween– (Is successor lock actually required?)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 103
Same Abstraction Map
• S(head) =– { x | there exists a such that
•a reachable from head and•a.item = x
– }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 104
Representation Invariant
• Easy to check that– tail always reachable from head– Nodes sorted– No duplicates
Art of Multiprocessor Programming© Herlihy-Shavit 2007 105
Drawbacks
• Better than coarse-grained lock– Threads can traverse in parallel
• Still not ideal– Long chain of acquire/release locks– Inefficient– Threads working at the beginning of
the list may block other threads
Art of Multiprocessor Programming© Herlihy-Shavit 2007 106
Optimistic Synchronization
• Find nodes without locking• Lock nodes• Check that everything is OK
Art of Multiprocessor Programming© Herlihy-Shavit 2007 107
Optimistic: Traverse without Locking
b d ea
add(c)
Aha!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 108
Optimistic: Lock and Load
b d ea
add(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 109
What Can Possibly Go Wrong?
b d ea
add(c)
Aha!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 110
What Can Possibly Go Wrong?
b d ea
add(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 111
What Can Possibly Go Wrong?
b d ea
add(c)
remove(b)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 112
What Can Possibly Go Wrong?
b d ea
add(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 113
What Can Possibly Go Wrong?
b d ea
add(c)
c would be added between b and d, but b is
no more reachable (deleted)!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 114
Validate (1)
b d ea
add(c)
Yes, b still
reachable from head
Art of Multiprocessor Programming© Herlihy-Shavit 2007 115
What Else Can Go Wrong?
b d ea
add(c)
Aha!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 116
What Else Can Go Wrong?
b d ea
add(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 117
What Else Can Go Wrong?
b d ea
add(c)
add(b’)
b’
Art of Multiprocessor Programming© Herlihy-Shavit 2007 118
What Else Can Go Wrong?
b d ea
add(c)
b’
add(b’) invalidated by
add( c )!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 119
Optimistic: Validate(2)
b d ea
add(c)
Yes, b still
points to d
Art of Multiprocessor Programming© Herlihy-Shavit 2007 120
Optimistic: Linearization Point
b d ea
add(c)
c
Art of Multiprocessor Programming© Herlihy-Shavit 2007 121
Same Abstraction Map
• S(head) =– { x | there exists a such that
•a reachable from head and•a.item = x
– }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 122
Invariants
• Careful: we may traverse deleted nodes
• But we establish properties by– Validation– After we lock target nodes
Art of Multiprocessor Programming© Herlihy-Shavit 2007 123
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 add and return true
Art of Multiprocessor Programming© Herlihy-Shavit 2007 124
Removing a Node
a b d e
remove(c)
Aha!
Art of Multiprocessor Programming© Herlihy-Shavit 2007 125
Validate (1)
a b d e
Yes, b still reachable from head
remove(c)
Art of Multiprocessor Programming© Herlihy-Shavit 2007 126
Validate (2)
a b d e
remove(c)
Yes, b still points to
d
Art of Multiprocessor Programming© Herlihy-Shavit 2007 127
OK Computer
a b d e
remove(c)
return false
Art of Multiprocessor Programming© Herlihy-Shavit 2007 128
Correctness
• If– Nodes b and d both locked– Node b still accessible– Node d still successor to b
• Then– No thread can remove b, d, e– No thread can add a node between b and d
or between d and e– OK to remove node or return false
Art of Multiprocessor Programming© Herlihy-Shavit 2007 129
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;}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 130
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 131
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
Begin at the beginning
Art of Multiprocessor Programming© Herlihy-Shavit 2007 132
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 133
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 134
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?
Art of Multiprocessor Programming© Herlihy-Shavit 2007 135
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 136
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 137
Remove: searchingpublic boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Art of Multiprocessor Programming© Herlihy-Shavit 2007 138
public boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Remove: searching
Search key
Art of Multiprocessor Programming© Herlihy-Shavit 2007 139
public boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Remove: searching
Retry on synchronization conflict
Art of Multiprocessor Programming© Herlihy-Shavit 2007 140
public boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Remove: searching
Examine predecessor and current nodes
Art of Multiprocessor Programming© Herlihy-Shavit 2007 141
public boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Remove: searching
Search by key
Art of Multiprocessor Programming© Herlihy-Shavit 2007 142
public boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Remove: searching
Stop if we find item
Art of Multiprocessor Programming© Herlihy-Shavit 2007 143
public boolean remove(Item item) { int key = item.hashCode(); retry: while (true) { Node pred = this.head; Node curr = pred.next; while (curr.key <= key) { if (item == curr.item) break; pred = curr; curr = curr.next; } … }
Remove: searching
Move along
Art of Multiprocessor Programming© Herlihy-Shavit 2007 144
On Exit from Loop
• If item is present– curr holds item– pred just before curr
• If item is absent– curr has first higher key– pred just before curr
• Assuming no synchronization problems
Art of Multiprocessor Programming© Herlihy-Shavit 2007 145
Remove: details on “…”try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.item == item) { pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Art of Multiprocessor Programming© Herlihy-Shavit 2007 146
try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.item == item) { pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Remove: details on “…”
Always unlock
Art of Multiprocessor Programming© Herlihy-Shavit 2007 147
try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.item == item) { pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Remove: details on “…”
Lock both nodes
Art of Multiprocessor Programming© Herlihy-Shavit 2007 148
try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.item == item) { pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Remove: details on “…”
Check for synchronization
conflicts
Art of Multiprocessor Programming© Herlihy-Shavit 2007 149
try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.item == item) { pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Remove: details on “…”
target found, remove node
Art of Multiprocessor Programming© Herlihy-Shavit 2007 150
try { pred.lock(); curr.lock(); if (validate(pred,curr) { if (curr.item == item) { pred.next = curr.next; return true; } else return false; }} finally {
pred.unlock();curr.unlock();
}
Remove: details on “…”
target not found
Art of Multiprocessor Programming© Herlihy-Shavit 2007 151
Optimistic List
• Limited hot-spots– Targets of add(), remove(), contains()– No contention on traversals
• Moreover– Traversals are wait-free– Food for thought …
Art of Multiprocessor Programming© Herlihy-Shavit 2007 152
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
Art of Multiprocessor Programming© Herlihy-Shavit 2007 153
Evaluation
• Optimistic is effective if– cost of scanning twice without locks
less than– cost of scanning once with locks
• Drawback– contains() acquires locks– 90% of calls in many apps
top related