1.77k likes | 2k Views
Concurrent Objects. 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. Concurrent Computation. memory. object. object. Objectivism.
E N D
Concurrent Objects Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & NirShavit Modified by PavolČerný, Programming Paradigms for Concurrency, Fall 2010, IST Austria
Concurrent Computation memory object object Art of Multiprocessor Programming
Objectivism What is a concurrent object? How do we describe one? How do we implement one? How do we tell if we’re right? Art of Multiprocessor Programming
Objectivism What is a concurrent object? How do we describe one? How do we tell if we’re right? Art of Multiprocessor Programming
FIFO Queue: Enqueue Method q.enq( ) Art of Multiprocessor Programming
FIFO Queue: Dequeue Method q.deq()/ Art of Multiprocessor Programming
A Lock-Based Queue class LockBasedQueue<T> { int head, tail; T[] items; Lock lock; public LockBasedQueue(int capacity) { head = 0; tail = 0; lock = new ReentrantLock(); items = (T[]) new Object[capacity]; } Art of Multiprocessor Programming
A Lock-Based Queue head tail 0 1 y z capacity-1 2 class LockBasedQueue<T> { inthead, tail; T[] items; Lock lock; public LockBasedQueue(int capacity) { head = 0; tail = 0; lock = new ReentrantLock(); items = (T[]) new Object[capacity]; } Queue fields protected by single shared lock Art of Multiprocessor Programming
A Lock-Based Queue head tail 0 1 y z capacity-1 2 class LockBasedQueue<T> { int head, tail; T[] items; Lock lock; publicLockBasedQueue(int capacity) { head = 0; tail = 0; lock = newReentrantLock(); items = (T[]) new Object[capacity]; } Initially head = tail Art of Multiprocessor Programming
Implementation: Deq head tail 0 1 y z capacity-1 2 publicT deq() throwsEmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally { lock.unlock(); } } Art of Multiprocessor Programming
Implementation: Deq head tail 0 1 y z capacity-1 2 public T deq() throws EmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally { lock.unlock(); } } Method calls mutually exclusive Art of Multiprocessor Programming
Implementation: Deq head tail 0 1 y z capacity-1 2 public T deq() throws EmptyException { lock.lock(); try { if(tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally { lock.unlock(); } } If queue empty throw exception Art of Multiprocessor Programming
Implementation: Deq head tail 0 1 y z capacity-1 2 public T deq() throws EmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally { lock.unlock(); } } Queue not empty: remove item and update head Art of Multiprocessor Programming
Implementation: Deq head tail 0 1 y z capacity-1 2 public T deq() throws EmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; returnx; } finally { lock.unlock(); } } Return result Art of Multiprocessor Programming
Implementation: Deq head tail 0 1 y z capacity-1 2 public T deq() throws EmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally{ lock.unlock(); } } Release lock no matter what! Art of Multiprocessor Programming
Implementation: Deq publicT deq() throwsEmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally { lock.unlock(); } } Should be correct because modifications are mutually exclusive… Art of Multiprocessor Programming
List-Based Set Interface: • Unordered collection of items, No duplicates • add(x)putxin set • remove(x)takexout of set • contains(x)tests if xin set Implementation: … -∞ 3 5 ∞
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) prev curr 7 3 9 5 curr prev P2: remove(5) Step 1
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) prev curr 7 3 9 5 prev.next:= curr.next curr prev P2: remove(5)
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) 7 3 9 5 P2: remove(5) Step 2
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) 7 3 9 5 P2: remove(5) Step 3
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) 7 3 9 5 P2: remove(5) Step 4
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) 7 3 9 5 P2: remove(5) Step 5
Concurrent lists Concurrent lists “lock what you modify” P1: remove(7) 7 3 9 5 P2: remove(5)
Lock-free list Lock-free linked list from [Herlihy-Shavit] public booleanremove(T item) { while (true) { (pred,curr) = find(head, key); if (curr.key != key) {// the key not present return false; } else {// the key present Node succ = curr.next.getReference(); snip = curr.next.attemptMark(succ, true); if (!snip) continue; pred.next.compareAndSet(curr, succ, false, false); return true; } } } p.attemptMark(T expRef, bool b) If p==expRef, update the mark p.compareAndSet(T expRef, T newRef, boolexpMark, boolnewMark) If p==expRef, p.mark==expMark, update the mark
Lock-free list remove remove(7) succ prev curr M 7 3 9 5 snip = curr.next.attemptMark(succ, true); … snip = pred.next.compareAndSet(curr,succ, false, false);
Defining concurrent implementations Need a way to specify a concurrent queue (concurrent list) object Need a way to prove that an algorithm implements the object’s specification Lets talk about object specifications … Art of Multiprocessor Programming
Correctness and Progress Lets begin with correctness • In a concurrent setting, we need to specify both the safety and the liveness properties of an object • Need a way to define • when an implementation is correct • the conditions under which it guarantees progress Art of Multiprocessor Programming
Sequential Objects Each object has a state Usually given by a set of fields Queue example: sequence of items Each object has a set of methods Only way to manipulate state Queue example: enqand deq methods Art of Multiprocessor Programming
Sequential Specifications If (precondition) the object is in such-and-such a state before you call the method, Then (postcondition) the method will return a particular value or throw a particular exception. and (postcondition, con’t) the object will be in some other state when the method returns, Art of Multiprocessor Programming
Pre and PostConditions for Dequeue Precondition: Queue is non-empty Postcondition: Returns first item in queue Postcondition: Removes first item in queue Art of Multiprocessor Programming
Pre and PostConditions for Dequeue Precondition: Queue is empty Postcondition: Throws Empty exception Postcondition: Queue state unchanged Art of Multiprocessor Programming
Why Sequential Specifications Totally Rock Interactions among methods captured by side-effects on object state State meaningful between method calls Documentation size linear in number of methods Each method described in isolation Can add new methods Without changing descriptions of old methods Art of Multiprocessor Programming
What About Concurrent Specifications ? Methods? Documentation? Adding new methods? Art of Multiprocessor Programming
Methods Take Time time time Art of Multiprocessor Programming
Methods Take Time invocation 12:00 q.enq(...) time time Art of Multiprocessor Programming
Methods Take Time invocation 12:00 q.enq(...) time Method call time Art of Multiprocessor Programming
Methods Take Time invocation 12:00 q.enq(...) time Method call time Art of Multiprocessor Programming
Methods Take Time invocation 12:00 response 12:01 q.enq(...) void time Method call time Art of Multiprocessor Programming
Sequential vs Concurrent Sequential Methods take time? Who knew? Concurrent Method call is not an event Method call is an interval. Art of Multiprocessor Programming
Concurrent Methods Take Overlapping Time time time Art of Multiprocessor Programming
Concurrent Methods Take Overlapping Time time Method call time Art of Multiprocessor Programming
Concurrent Methods Take Overlapping Time time Method call Method call time Art of Multiprocessor Programming
Concurrent Methods Take Overlapping Time time Method call Method call Method call time Art of Multiprocessor Programming
Sequential vs Concurrent Sequential: Object needs meaningful state only between method calls Concurrent Because method calls overlap, object might never be between method calls Art of Multiprocessor Programming
Sequential vs Concurrent Sequential: Each method described in isolation Concurrent Must characterize all possible interactions with concurrent calls What if two enqs overlap? Two deqs? enq and deq? … Art of Multiprocessor Programming
Sequential vs Concurrent Sequential: Can add new methods without affecting older methods Concurrent: Everything can potentially interact with everything else Art of Multiprocessor Programming
Sequential vs Concurrent Sequential: Can add new methods without affecting older methods Concurrent: Everything can potentially interact with everything else Panic! Art of Multiprocessor Programming
The Big Question What does it mean for a concurrent object to be correct? What is a concurrent FIFO queue? FIFO means strict temporal order Concurrent means ambiguous temporal order Art of Multiprocessor Programming
Intuitively… publicT deq() throwsEmptyException { lock.lock(); try { if (tail == head) throw new EmptyException(); T x = items[head % items.length]; head++; return x; } finally { lock.unlock(); } } Art of Multiprocessor Programming