Lecture 6-2 : Concurrent Queues and Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.

Slides:



Advertisements
Similar presentations
Operating Systems Semaphores II
Advertisements

Concurrent Queues and Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Scalable Flat-Combining Based Synchronous Queues Danny Hendler, Itai Incze, Nir Shavit and Moran Tzafrir Presentation by Uri Golani.
Operating Systems: Monitors 1 Monitors (C.A.R. Hoare) higher level construct than semaphores a package of grouped procedures, variables and data i.e. object.
– R 7 :: 1 – 0024 Spring 2010 Parallel Programming 0024 Recitation Week 7 Spring Semester 2010.
Maged M. Michael, “Hazard Pointers: Safe Memory Reclamation for Lock- Free Objects” Presentation Robert T. Bauer.
Monitors & Blocking Synchronization 1. Producers & Consumers Problem Two threads that communicate through a shared FIFO queue. These two threads can’t.
CMSC 330: Organization of Programming Languages Threads Classic Concurrency Problems.
Stacks, Queues, and Deques. 2 A stack is a last in, first out (LIFO) data structure Items are removed from a stack in the reverse order from the way they.
Stacks  a data structure which stores data in a Last-in First-out manner (LIFO)  has a pointer called TOP  can be implemented by either Array or Linked.
Concurrent Queues and Stacks The Art of Multiprocessor Programming Spring 2007.
CS Data Structures II Review COSC 2006 April 14, 2017
Scalable Synchronous Queues By William N. Scherer III, Doug Lea, and Michael L. Scott Presented by Ran Isenberg.
Concurrent Queues Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Art of Multiprocessor Programming1 Concurrent Queues Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit Modified.
Concurrent Queues and Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Concurrent Queues and Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Shared Counters and Parallelism Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Monitors and Blocking Synchronization By Tal Walter.
Introduction to Lock-free Data-structures and algorithms Micah J Best May 14/09.
Simple, Fast, and Practical Non- Blocking and Blocking Concurrent Queue Algorithms Presenter: Jim Santmyer By: Maged M. Micheal Michael L. Scott Department.
Concurrent Queues and Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Stacks, Queues, and Deques
שירן חליבה Concurrent Queues. Outline: Some definitions 3 queue implementations : A Bounded Partial Queue An Unbounded Total Queue An Unbounded Lock-Free.
DATA STRUCTURES AND ALGORITHMS Lecture Notes 4 Prepared by İnanç TAHRALI.
Semaphores, Locks and Monitors By Samah Ibrahim And Dena Missak.
Data Structures (part 2). Stacks An Everyday Example Your boss keeps bringing you important items to deal with and keeps saying: “Put that last ‘rush’
Lecture7: Queue Bohyung Han CSE, POSTECH CSED233: Data Structures (2014F)
Producer-Consumer Problem The problem describes two processes, the producer and the consumer, who share a common, fixed-size buffer used as a queue.bufferqueue.
מרצה: יהודה אפק מגיש: ערן שרגיאן. OutlineOutline Quick reminder of the Stack structure. The Unbounded Lock-Free Stack. The Elimination Backoff Stack.
JAVA MEMORY MODEL AND ITS IMPLICATIONS Srikanth Seshadri
11/21/20151 Operating Systems Design (CS 423) Elsa L Gunter 2112 SC, UIUC Based on slides by Roy Campbell, Sam.
Advanced Locking Techniques
1 CMSC421: Principles of Operating Systems Nilanjan Banerjee Principles of Operating Systems Acknowledgments: Some of the slides are adapted from Prof.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Software Systems Advanced Synchronization Emery Berger and Mark Corner University.
Monitors and Blocking Synchronization Dalia Cohn Alperovich Based on “The Art of Multiprocessor Programming” by Herlihy & Shavit, chapter 8.
Concurrent Queues Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Gal Milman Based on Chapter 10 (Concurrent Queues and the ABA Problem) in The Art of Multiprocessor Programming by Herlihy and Shavit Seminar 2 (236802)
Programming Language Basics Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
COSC 3407: Operating Systems Lecture 9: Readers-Writers and Language Support for Synchronization.
Concurrent Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Shared Counters and Parallelism Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Scalable lock-free Stack Algorithm Wael Yehia York University February 8, 2010.
“The desire for safety stands against every great and noble enterprise.” – Tacitus Thought for the Day.
Chapter 4 ADTs Stack and Queue. 4-2 Formal ADT Specifications The Java interface construct lets us collect together method interfaces into a syntactic.
M180: Data Structures & Algorithms in Java Stacks Arab Open University 1.
Distributed Algorithms (22903) Lecturer: Danny Hendler Lock-free stack algorithms.
Concurrency: Locks and synchronization Slides by Prof. Cox.
1 Stacks Abstract Data Types (ADTs) Stacks Application to the analysis of a time series Java implementation of a stack Interfaces and exceptions.
1 Lecture 9: Stack and Queue. What is a Stack Stack of Books 2.
Lecture 9 : Concurrent Data Structures Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit.
Dale Roberts Department of Computer and Information Science, School of Science, IUPUI CSCI 240 Abstract Data Types Queues Dale Roberts, Lecturer
Linked Data Structures
Lecture 6-1 : Concurrent Data Structures (Concurrent Linked Lists)
Checking nonblocking concurrent queue program
Monitors and Blocking Synchronization
Practice Session 8 Lockfree LinkedList Blocking queues
Concurrent Objects Companion slides for
Distributed Algorithms (22903)
Distributed Algorithms (22903)
Distributed Algorithms (22903)
Concurrent Queues and Stacks
Concurrent Queues and Stacks
Producer-Consumer Problem
ADT list.
Barrier Synchronization
Stacks, Queues, and Deques
Lecture 16 Stacks and Queues CSE /26/2018.
Lecture 9: Stack and Queue
Presentation transcript:

Lecture 6-2 : Concurrent Queues and Stacks Companion slides for The Art of Multiprocessor Programming by Maurice Herlihy & Nir Shavit

pool Data Structure similar to Set –Does not necessarily provide contains() method –Allows the same item to appear more than once –get() and set() Art of Multiprocessor Programming© Herlihy-Shavit public interface Pool { void put(T item); T get(); }

Art of Multiprocessor Programming© Herlihy-Shavit Queues & Stacks Both: pool of items Queue –enq() & deq() –First-in-first-out (FIFO) order Stack –push() & pop() –Last-in-first-out (LIFO) order

Art of Multiprocessor Programming© Herlihy-Shavit Bounded vs Unbounded Bounded –Fixed capacity –Good when resources an issue Unbounded –Holds any number of objects

Art of Multiprocessor Programming© Herlihy-Shavit Blocking vs Non-Blocking Problem cases: –Removing from empty pool –Adding to full (bounded) pool Blocking –Caller waits until state changes Non-Blocking –Method throws exception

Art of Multiprocessor Programming© Herlihy-Shavit Queue: Concurrency enq(x) y=deq() enq() and deq() work at different ends of the object tailhead

Art of Multiprocessor Programming© Herlihy-Shavit Concurrency enq(x) Challenge: what if the queue is empty or full? y=deq() tail head

Art of Multiprocessor Programming© Herlihy-Shavit A Bounded Lock-Based Queue public class BoundedQueue { ReentrantLock enqLock, deqLock; Condition notEmptyCondition, notFullCondition; AtomicInteger size; Node head; Node tail; int capacity; public BoundedQueue(int capacity) { this.capacity = capacity; this.head = new Node(null); this.tail = head; this.size = new AtomicInteger(0); this.enqLock = new ReentrantLock(); this.notFullCondition = enqLock.newCondition(); this.deqLock = new ReentrantLock(); this.notEmptyCondition = deqLock.newCondition(); } protected class Node { public T value; public Node next; public Node(T x) { value = x; next = null; }

9 public void enq(T x) { boolean mustWakeDequeuers = false; enqLock.lock(); try { while (size.get() == capacity) notFullCondition.await(); Node e = new Node(x); tail.next = e; tail = e; if (size.getAndIncrement() == 0) { mustWakeDequeuers = true; } } finally { enqLock.unlock(); } if (mustWakeDequeuers) { deqLock.lock(); try { notEmptyCondition.signalAll(); } finally { deqLock.unlock(); } public T deq() { T result; boolean mustWakeEnqueuers = false; deqLock.lock(); try { while (size.get() == 0) { notEmptyCondition.await(); result = head.next.value; head = head.next; if (size.getAndDecrement() == capacity) { mustWakeEnqueuers = true; } } finally { deqLock.unlock(); } if (mustWakeEnqueuers) { enqLock.lock(); try { notFullCondition.signalAll(); } finally { enqLock.unlock(); } return result; }

lock enqLock/deqLock –At most one enqueuer/dequeuer at a time can manipulate the queue’s fields Two locks –Enqueuer does not lock out dequeuer –vice versa Association –enqLock associated with notFullCondition –deqLock associated with notEmptyCondition Art of Multiprocessor Programming© Herlihy-Shavit

enqueue 1.Acquires enqLock 2.Reads the size field 3.If full, enqueuer must wait until dequeuer makes room 4.enqueuer waits on notFullCondition field, releasing enqLock temporarily, and blocking until that condition is signaled. 5.Each time the thread awakens, it checks whether there is a room, and if not, goes back to sleep 6.Insert new item into tail 7.Release enqLock 8.If queue was empty, notify/signal waiting dequeuers Art of Multiprocessor Programming© Herlihy-Shavit

dequeue 1.Acquires deqLock 2.Reads the size field 3.If empty, dequeuer must wait until item is enqueued 4.dequeuer waits on notEmptyCondition field, releasing deqLock temporarily, and blocking until that condition is signaled. 5.Each time the thread awakens, it checks whether item was enqueued, and if not, goes back to sleep 6.Assigne the value of head’s next node to “result” and reset head to head’s next node 7.Release deqLock 8.If queue was full, notify/signal waiting enqueuers 9.Return “result” Art of Multiprocessor Programming© Herlihy-Shavit

Art of Multiprocessor Programming13 Bounded Queue Sentinel head tail

Art of Multiprocessor Programming14 Bounded Queue head tail First actual item

Art of Multiprocessor Programming15 Bounded Queue head tail Lock out other deq() calls deqLock

Art of Multiprocessor Programming16 Bounded Queue head tail Lock out other enq() calls deqLock enqLock

Art of Multiprocessor Programming17 Not Done Yet head tail deqLock enqLock Need to tell whether queue is full or empty

Art of Multiprocessor Programming18 Not Done Yet head tail deqLock enqLock Max size is 8 items size 1

Art of Multiprocessor Programming19 Not Done Yet head tail deqLock enqLock Incremented by enq() Decremented by deq() size 1

Art of Multiprocessor Programming20 Enqueuer head tail deqLock enqLock size 1 Lock enqLock

Art of Multiprocessor Programming21 Enqueuer head tail deqLock enqLock size 1 Read size OK

Art of Multiprocessor Programming22 Enqueuer head tail deqLock enqLock size 1 No need to lock tail

Art of Multiprocessor Programming23 Enqueuer head tail deqLock enqLock size 1 Enqueue Node

Art of Multiprocessor Programming24 Enqueuer head tail deqLock enqLock size 1 2 getAndincrement()

Art of Multiprocessor Programming25 Enqueuer head tail deqLock enqLock size 8 Release lock 2

Art of Multiprocessor Programming26 Enqueuer head tail deqLock enqLock size 2 If queue was empty, notify waiting dequeuers

Art of Multiprocessor Programming27 Unsuccesful Enqueuer head tail deqLock enqLock size 8 Uh- oh Read size …

Art of Multiprocessor Programming28 Dequeuer head tail deqLock enqLock size 2 Lock deqLock

Art of Multiprocessor Programming29 Dequeuer head tail deqLock enqLock size 2 Read sentinel’s next field OK

Art of Multiprocessor Programming30 Dequeuer head tail deqLock enqLock size 2 Read value

Art of Multiprocessor Programming31 Dequeuer head tail deqLock enqLock size 2 Make first Node new sentinel

Art of Multiprocessor Programming32 Dequeuer head tail deqLock enqLock size 1 Decrement size

Art of Multiprocessor Programming33 Dequeuer head tail deqLock enqLock size 1 Release deqLock

Art of Multiprocessor Programming© Herlihy-Shavit Monitor Locks Java ReentrantLocks are monitors Allow blocking on a condition rather than spinning Threads: –acquire and release lock –wait on a condition

Art of Multiprocessor Programming© Herlihy-Shavit public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit); Condition newCondition(); void unlock; } The Java Lock Interface Create condition to wait on

Art of Multiprocessor Programming© Herlihy-Shavit Lock Conditions public interface Condition { void await(); boolean await(long time, TimeUnit unit); … void signal(); void signalAll(); }

Art of Multiprocessor Programming© Herlihy-Shavit public interface Condition { void await(); boolean await(long time, TimeUnit unit); … void signal(); void signalAll(); } Lock Conditions Release lock and wait on condition

Art of Multiprocessor Programming© Herlihy-Shavit public interface Condition { void await(); boolean await(long time, TimeUnit unit); … void signal(); void signalAll(); } Lock Conditions Wake up one waiting thread

Art of Multiprocessor Programming© Herlihy-Shavit public interface Condition { void await(); boolean await(long time, TimeUnit unit); … void signal(); void signalAll(); } Lock Conditions Wake up all waiting threads

Art of Multiprocessor Programming© Herlihy-Shavit Await Releases lock associated with q Sleeps (gives up processor) Awakens (resumes running) Reacquires lock & returns q.await()

Art of Multiprocessor Programming© Herlihy-Shavit Signal Awakens one waiting thread –Which will reacquire lock q.signal();

Art of Multiprocessor Programming© Herlihy-Shavit Signal All Awakens all waiting threads –Which will each reacquire lock q.signalAll();

Unbounded Lock-Free Queue (Nonblocking) Unbounded –No need to count the number of items Lock-free –Use AtomicReference An object reference that may be updated atomically. –boolean compareAndSet(V expect, V update) Atomically sets the value to the given updated value if the current value == the expected value. Nonblocking –No need to provide conditions on which to wait 43

Art of Multiprocessor Programming44 A Lock-Free Queue Sentinel head tail

Art of Multiprocessor Programming45 Enqueue head tail Enq( )

Art of Multiprocessor Programming46 Enqueue head tail

Art of Multiprocessor Programming47 Logical Enqueue head tail CAS

Art of Multiprocessor Programming48 Physical Enqueue head tail CAS

Art of Multiprocessor Programming49 Enqueue These two steps are not atomic The tail field refers to either –Actual last Node (good) –Penultimate Node (not so good) Be prepared!

Art of Multiprocessor Programming50 Enqueue What do you do if you find –A trailing tail? Stop and help fix it –If tail node has non-null next field –CAS the queue’s tail field to tail.next As in the universal construction

Art of Multiprocessor Programming51 When CASs Fail During logical enqueue –Abandon hope, restart –Still lock-free (why?) During physical enqueue –Ignore it (why?)

Art of Multiprocessor Programming52 Dequeuer head tail Read value

Art of Multiprocessor Programming53 Dequeuer head tail Make first Node new sentinel CAS

Art of Multiprocessor Programming© Herlihy-Shavit Unbounded Lock-Free Queue (Nonblocking) public class LockFreeQueue { private AtomicReference head; private AtomicReference tail; public LockFreeQueue() { this.head = new AtomicReference (null); this.tail = new AtomicReference (null); } public class Node { public T value; public AtomicReference next; public Node(T value) { this.value = value; this.next = new AtomicReference (null); }

55 public void enq(T item) { Node node = new Node(item); while (true) { Node last = tail.get(); Node next = last.next.get(); if (last == tail.get()) { if (next == null) { if (last.next.compareAndSet(next, node)) { tail.compareAndSet(last, node); return; } } else { tail.compareAndSet(last, next); } public T deq() throws EmptyException { while (true) { Node first = head.get(); Node last = tail.get(); Node next = first.next.get(); if (first == head.get()) { if (first == last) { if (next = null) { throw new EmptyException(); } tail.compareAndSet(last, next); } else { T value = next.value; if (head.compareAndSet(first,next)) return value; } Unbounded Lock-Free Queue (Nonblocking)

Art of Multiprocessor Programming56 Concurrent Stack Methods –push(x) –pop() Last-in, First-out (LIFO) order Lock-Free!

Art of Multiprocessor Programming57 Empty Stack Top

Art of Multiprocessor Programming58 Push Top

Art of Multiprocessor Programming59 Push Top CAS

Art of Multiprocessor Programming60 Push Top

Art of Multiprocessor Programming61 Push Top

Art of Multiprocessor Programming62 Push Top

Art of Multiprocessor Programming63 Push Top CAS

Art of Multiprocessor Programming64 Push Top

Art of Multiprocessor Programming65 Pop Top

Art of Multiprocessor Programming66 Pop Top CAS

Art of Multiprocessor Programming67 Pop Top CAS mine !

Art of Multiprocessor Programming68 Pop Top CAS

Art of Multiprocessor Programming69 Pop Top

Art of Multiprocessor Programming70 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff(); }} Lock-free Stack

Art of Multiprocessor Programming71 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public Boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack tryPush attempts to push a node

Art of Multiprocessor Programming72 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack Read top value

Art of Multiprocessor Programming73 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack current top will be new node’s successor

Art of Multiprocessor Programming74 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack Try to swing top, return success or failure

Art of Multiprocessor Programming75 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack Push calls tryPush

Art of Multiprocessor Programming76 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack Create new node

Art of Multiprocessor Programming77 public class LockFreeStack { private AtomicReference top = new AtomicReference(null); public boolean tryPush(Node node){ Node oldTop = top.get(); node.next = oldTop; return(top.compareAndSet(oldTop, node)) } public void push(T value) { Node node = new Node(value); while (true) { if (tryPush(node)) { return; } else backoff.backoff() }} Lock-free Stack If tryPush() fails, back off before retrying

78 protected boolean tryPush(Node node) { Node oldTop = top.get(); node.next = oldTop; return (top.compareAndSet(oldTop, node)); } public void push( T value ) { Node node = new Node( value ); while (true) { if (tryPush(node)) { return; } else { backoff.backoff( ); } } protected Node tryPop( ) throws EmptyException { Node oldTop = top.get(); if ( oldTop == null ) { throw new EmptyException( ); } Node newTop = oldTop.next; if ( top.compareAndSet( oldTop, newTop ) ) { return oldTop; } else { return null; } } public T pop() throws EmptyException { while (true) { Node returnNode = tryPop( ); if ( returnNode != null ) { return returnNode.value; } else { backoff.backoff( ); } } Unbounded Lock-Free Stack

Art of Multiprocessor Programming79 Lock-free Stack Good –No locking Bad –Without GC, fear ABA –Without backoff, huge contention at top –In any case, no parallelism

Art of Multiprocessor Programming80 Question Are stacks inherently sequential? Reasons why –Every pop() call fights for top item Reasons why not –Think about it!