Download presentation
Presentation is loading. Please wait.
Published byVincent Kennedy Modified over 9 years ago
1
Concurrent Linked Lists and Linearizability Proofs Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified by Pavol Černý, Programming Paradigms for Concurrency, Fall 2010, IST Austria
2
Art of Multiprocessor Programming2 First: Issues in Linearizability Q1: Are linearizability proofs composable? Q2: Linearizability vs (strict) serializability
3
Art of Multiprocessor Programming 3 Linearizability History H is linearizable if it can be extended to G by –Appending zero or more responses to pending invocations –Discarding other pending invocations So that G is equivalent to –Legal sequential history S –where G S
4
Art of Multiprocessor Programming 4 Linearizability Equivalently: Each method should –take effect instantaneously –between invocation and response events –object is correct if this “ sequential ” behavior is correct
5
Art of Multiprocessor Programming 5 Composability Theorem History H is linearizable if and only if –For every object x –H|x is linearizable (proof on the board)
6
Art of Multiprocessor Programming 6 Linearizability vs (strict) serializability Serializability: A history is serializable if it is equivalent to one in which transactions appear to execute sequentially (without interleaving) Strict serializability: In addition, the order of transactions in the sequential history respects precedence order from the interleaved history Linearizability: A special case of strict serializability, where each “transaction” (method) accesses a single object (Strict) serializability non-local.
7
Art of Multiprocessor Programming7 Today: Concurrent Objects Adding threads should not lower throughput –Contention effects Should increase throughput –Not possible if inherently sequential –Surprising things are parallelizable
8
Art of Multiprocessor Programming8 Coarse-Grained Synchronization Each method locks the object –Avoid contention using queue locks
9
Art of Multiprocessor Programming9 Coarse-Grained Synchronization Each method locks the object –Avoid contention using queue locks –Easy to reason about In simple cases
10
Art of Multiprocessor Programming10 Coarse-Grained Synchronization Each method locks the object –Avoid contention using queue locks –Easy to reason about In simple cases So, are we done?
11
Art of Multiprocessor Programming11 Coarse-Grained Synchronization Sequential bottleneck –Threads “stand in line”
12
Art of Multiprocessor Programming12 Coarse-Grained Synchronization Sequential bottleneck –Threads “stand in line” Adding more threads –Does not improve throughput –Struggle to keep it from getting worse
13
Art of Multiprocessor Programming13 Coarse-Grained Synchronization Sequential bottleneck –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 …
14
Art of Multiprocessor Programming14 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 For us: example for proofs of linearizability
15
Art of Multiprocessor Programming15 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
16
Art of Multiprocessor Programming16 List-Based Sets public interface Set { public boolean add(T x); public boolean remove(T x); public boolean contains(T x); }
17
Art of Multiprocessor Programming17 List Node public class Node { public T item; public int key; public Node next; }
18
Art of Multiprocessor Programming18 List Node public class Node { public T item; public int key; public Node next; } item of interest
19
Art of Multiprocessor Programming19 List Node public class Node { public T item; public int key; public Node next; } Usually hash code
20
Art of Multiprocessor Programming20 List Node public class Node { public T item; public int key; public Node next; } Reference to next node
21
Art of Multiprocessor Programming21 The List-Based Set abc Sorted with Sentinel nodes (min & max possible keys) -∞ +∞
22
Art of Multiprocessor Programming22 Invariants Sentinel nodes –tail reachable from head Sorted No duplicates
23
Art of Multiprocessor Programming23 Sequential List Based Set a c d a b c Add() Remove()
24
Art of Multiprocessor Programming24 Sequential List Based Set a c d b a b c Add() Remove()
25
Art of Multiprocessor Programming25 Coarse Grained Locking a b d
26
Art of Multiprocessor Programming26 Coarse Grained Locking a b d c
27
Art of Multiprocessor Programming27 honk! Coarse Grained Locking a b d c Simple but hotspot + bottleneck honk!
28
Art of Multiprocessor Programming28 Coarse-Grained Locking Easy, same as synchronized methods –“One lock to rule them all …”
29
Art of Multiprocessor Programming29 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
30
Art of Multiprocessor Programming30 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
31
Art of Multiprocessor Programming31 Hand-over-Hand locking abc
32
Art of Multiprocessor Programming32 Hand-over-Hand locking abc
33
Art of Multiprocessor Programming33 Hand-over-Hand locking abc
34
Art of Multiprocessor Programming34 Hand-over-Hand locking abc
35
Art of Multiprocessor Programming35 Hand-over-Hand locking abc
36
Art of Multiprocessor Programming36 Removing a Node abcd remove(b)
37
Art of Multiprocessor Programming37 Removing a Node abcd remove(b)
38
Art of Multiprocessor Programming38 Removing a Node abcd remove(b)
39
Art of Multiprocessor Programming39 Removing a Node abcd remove(b)
40
Art of Multiprocessor Programming40 Removing a Node abcd remove(b)
41
Art of Multiprocessor Programming41 Removing a Node acd remove(b) Why hold 2 locks?
42
Art of Multiprocessor Programming42 Remove method public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }}
43
Art of Multiprocessor Programming43 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
44
Art of Multiprocessor Programming44 Remove method public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { currNode.unlock(); predNode.unlock(); }} Predecessor and current nodes
45
Art of Multiprocessor Programming45 Remove method public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }} Make sure locks released
46
Art of Multiprocessor Programming46 Remove method public boolean remove(Item item) { int key = item.hashCode(); Node pred, curr; try { … } finally { curr.unlock(); pred.unlock(); }} Everything else
47
Art of Multiprocessor Programming47 Remove method try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); … } finally { … }
48
Art of Multiprocessor Programming48 Remove method try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); … } finally { … } lock pred == head
49
Art of Multiprocessor Programming49 Remove method try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); … } finally { … } Lock current
50
Art of Multiprocessor Programming50 Remove method try { pred = this.head; pred.lock(); curr = pred.next; curr.lock(); … } finally { … } Traversing list
51
Art of Multiprocessor Programming51 Remove: searching 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;
52
Art of Multiprocessor Programming52 Remove: searching 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
53
Art of Multiprocessor Programming53 Remove: searching 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
54
Art of Multiprocessor Programming54 Remove: searching 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
55
Art of Multiprocessor Programming55 Remove: searching 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 node found, remove it
56
Art of Multiprocessor Programming56 Remove: searching 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
57
Art of Multiprocessor Programming57 Remove: searching 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!
58
Art of Multiprocessor Programming58 Remove: searching 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
59
Art of Multiprocessor Programming59 Remove: searching 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
60
Art of Multiprocessor Programming60 Remove: searching 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
61
Art of Multiprocessor Programming61 Remove: searching 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
62
Art of Multiprocessor Programming62 Adding Nodes To add node e –Must lock predecessor –Must lock successor Neither can be deleted
63
Proving linearizability Rely-guarantee approach –Vafeiadis, Herlihy, Hoare, Shapiro 2006 Reduction approach –Elmas, Qadeer, Tasiran 2009 Art of Multiprocessor Programming63
64
Rely-guarantee Sequential programs: {p}C{q} -- Hoare logic Parallel programs: C models (p,R,G,q) Art of Multiprocessor Programming64
65
Rely-guarantee Parallel programs: C models (p,R,G,q) p – precondition – state predicate q – postcondition – transition predicate R – rely conditions – what we tolearte from other threads G – guarantee conditions – we do our part Art of Multiprocessor Programming65
66
Rely-guarantee Rules: {p}C{q} in Hoare logic models (p,R,G,q) Art of Multiprocessor Programming66 C1 models (p1,R,G,q1) C2 models (p2,R,G,q2) q1 -> p2 C1;C2 models (p1,R,G,(q1;R*;q2))
67
Rely-guarantee Art of Multiprocessor Programming67 C1 models (p1,R1,G1,q1) G2 -> R1 C2 models (p2,R2,G2,q2) G1 -> R2 C1 || C2 models (p1&p2,R1&R2,G1 or G2,q) where q is q1;(R1&R2)*;q2 or q1;(R1&R2)*;q2
68
68 Example: increment local int t; acquire (lock); t := x; t := t + 1; x := t; release (lock); global int x; x := 0; || assert (x == 2); local int t; acquire (lock); t := x; t := t + 1; x := t; release (lock);
69
69 Example: increment Rely condition R: L.owner = self -> x’=x Guarantee condition G: L.owner ≠ self -> x’=x We prove: P models (true,R,G,x’=x+1) P1||P2 models (true,R,G,x’=x+2) (proofs on the board)
70
Proving remove Art of Multiprocessor Programming70 AbsRemove(e): { AbsResult = (e in Abs); Abs = Abs – {e}} Strategy: 1. find linearization points 2. insert AbsRemove 3. prove that AbsResult = Result
71
71 Reduction proofs inc (): local int t; acquire (lock); t := x; t := t + 1; x := t; release(lock); Main: x := 0; inc(); || inc(); assert (x == 2); Slides adapted from Tayfun Elmas.
72
Art of Multiprocessor Programming72 Proof by reduction inc (): int t; acquire (lock); t := x; t := t + 1; x := t; release(lock); R B B B L inc (): int t; acquire (lock); t := x; t := t + 1; x := t; release(lock); inc (): x := x + 1; havoc t; REDUCE-SEQUENTIAL ABSTRACT
73
73 Reduction ; ; ... 1 2 ... n ... right-mover: For each execution: Exist equivalent executions: 73... 1 2 ... n ...... 1 2 ... n ................. 1 2 ... n ... ;
74
Art of Multiprocessor Programming 74 Static mover check - 1 Right mover: Commutes to the right of any other action run by a different thread Static right-mover check for : For every action in program: (run by different thread) ;; ; abstracted by
75
Art of Multiprocessor Programming75 Static mover check - 2 Static right-mover check between and : Simple cases Mover check passes: and access different variables Fails: and 1) simultaneously enabled and 2) perform conflicting accesses to a variable 75 ;; ; abstracted by
76
Abstraction rule: –Replace with if: Art of Multiprocessor Programming76 Abstraction abstracted by 76 Going wrong more often is sound for assertion checking Forall : error s1s1 s1s1 1. If then exists s1s1 2. If then exists s2s2 s1s1 s2s2 or error s1s1 s1s1
77
Art of Multiprocessor Programming77 Drawbacks of fine-grained locking lists Better than coarse-grained lock –Threads can traverse in parallel Still not ideal –Long chain of acquire/release –Inefficient
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.