1 / 19

Implementing a Two-Lock Concurrent Queue

Explore the implementation of a two-lock concurrent queue, modeling a simulation, identifying shared data, synchronization primitives, testing, and evaluating performance in Fall 2007. Understand the requirements, operations, and challenges faced during the implementation process.

lissettej
Download Presentation

Implementing a Two-Lock Concurrent Queue

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementing a Two-LockConcurrent Queue Hussain Tinwala Fall 2007

  2. Overview • Description & Requirements • Implementing the Queue • Modeling a Simulation • Identifying Shared Data • Using Synchronization Primitives • Testing and Performance

  3. Queue Description & Requirements (1) • Concurrent Queue (FIFO) • Concurrent Operations • Enqueue: add a new node to the back. • Dequeue: remove a node from the front. • Queue Access Points • Head Node • Tail Node • Internal Node Structure is a linked list

  4. Queue Description & Requirements (2) • Single Lock Queue All operations proceed one after another • Two Lock Queue Some operations can proceed at the same time

  5. Implementing the Queue (1) • Initial Queue Head Tail next dummy null

  6. Implementing the Queue (2) • Enqueue works with the tailLock Assume newNode is already created Part of the Enqueue Method

  7. Implementing the Queue (3) • Dequeue works with the headLock Part of the Dequeue Method

  8. Modeling a Simulation (1)

  9. Modeling a Simulation (2) • Enqueuer class and Dequeuer class share a Producer-Consumer Relationship • Enqueuer threads: • Start • Enqueue n times • Exit • Dequeuer threads: • Start • Dequeue until queue is empty. • Once the queue is empty, the Dequeuer thread will • Wait until new data arrives…. OR • Exit if no more data will arrive

  10. Modeling a Simulation (3) • Simulator Responsibilities: • Construct and Initialize the Queue • Spawn Enqueuer and Dequeuer threads with appropriate arguments • Number of nodes per Enqueue • Time to sleep • Provide a global repository for storing non-queue related shared data • Number of Enqueuer threads left (Why? --> Next slide)

  11. Identifying Shared Data • Instances of the following classes are shared between Enqueuers and Dequeuers: • Queue (to perform Enqueue/Dequeue operations) • Simulator • The Role of the Simulator class in the Producer-Consumer relationship • Used to inform Dequeuer (consumer) threads of: • Arrival of new Data • The end of production

  12. Using Synchronization Primitives (1) • The Dequeuer thread keeps running until there is no more data left in the queue. • Example: 2 Enqueuer threads (each enqueues 2 nodes, so 4 nodes in all), 1 Dequeuer threadNotation: [ThreadID, NodeNumber] [1,1] [2,1] • A Dequeuer thread now Dequeues twice [1,1] [2,1] The queue is now defined to be empty • The Dequeuer thread goes to sleep and Enqueuer threads continue [2,1] [2,2] [1,2] • The Enqueuer thread uses the Simulator to wake up Dequeuerand Enqueuer threads exit. [2,1] [2,2] [1,2] • The simulator announces that no more data will arrive. The Dequeuer • sees this by inspecting an integer in the shared Simulator object and exits.

  13. Using Synchronization Primitives (2) Synchronization actions used by the Enqueuer class There is a new node in the queue No more data will arrive (production has halted)

  14. Using Synchronization Primitives (3) Synchronization actions used by the Dequeuer class

  15. Using Synchronization Primitives (4) • Two synchronized methods: • decrementNumEnqsLeft • used by Enqueuer thread when exiting • getNumEnqsLeft • used by Dequeuer to inspect if production has halted

  16. Problems Faced • Many Dequeuers died before production (Enqueuers) halted. This was due to the queue being empty at some point. The numEnqsLeft variable was introduced to resolve this issue. • Dangling Dequeuer threads: • Decision to wait or quit was not atomic • Dequeuer threads got preempted just before they were about to wait. • Then, Enqueuers added nodes and quit. • Dequeuer threads resume and wait. • But now there are no Enqueuer threads left to notify them. • Solved by expanding the synchronized block so that decision to wait or quit is atomic.

  17. Testing the Implementation Printing output of operations resulted in random orderings Sample: If printing was synchronized, then Enqueue and Dequeue could not proceed concurrently --> defeats the purpose of a two-lock algorithm. Use post simulation sort: - At the end of the simulation, the output is sorted using the *nix sort utility based on the first number on each line. This is the nanoTime (System.nanoTime()) - Result: an accurate schedule of operations.

  18. Performance 120,000 Enqueue operations divided equally among Enqueuer threads

  19. Thank You Questions?

More Related