Scalable Synchronous Queues

Download Report

Transcript Scalable Synchronous Queues

Scalable Synchronous Queues
By William N. Scherer III, Doug Lea, and Michael L.
Scott
Presented by Ran Isenberg
Introduction

Queues are a way for different threads to
communicate and exchange information
between them.

In a thread-safe, concurrent and asynchronous
queue, consumers typically wait for producers
to make data available.

In a synchronous queue, producers similarly wait
for consumers to take the data – “a pair up”.
Hanson’s Synchronous Queue
Hanson’s Pros & Cons
Pros
 High design-level tractability.
 Using semaphores to target wakeups to only the
single producer or consumer thread that an
operation has unblocked.
Cons:
 May fall victim to priority inversion.
 Poor performance - employs three separate blocking
semaphores (locks).
Possible Solution?
Use non blocking synchronization!
Java 5.0 synchronous queue
The Java SE 5.0 synchronous queue (below) uses a pair of
queues (in fair mode; stacks for unfair mode) to separately hold
waiting producers and consumers.
Java 5.0 synchronous queue (Cont.)
Java 5 Version – Pros & Cons
Pros
 Uses a pair of queues to separately hold waiting producers
and consumers.
 Allows producers to publish data items as they arrive instead
of having to first awaken after blocking on a semaphore;
consumers need not wait.
 One transfer (put & take), requires only three
synchronization operations, compared to the six incurred by
Hanson’s.
Cons:
 Relies on one lock to protect access to both queues –
creates a narrow bottleneck during runtime.
Non-Blocking Synchronization


Non blocking concurrent objects avoid mutual
exclusion and locks.
Instead, they use atomic CAS operations (compare &
swap) to make sure object’s invariants still hold
afterwards.
Totalized operations:
 Operations that don't block and return a failure code in
case the preconditions aren't met.
 Example: dequeing from an empty queue will not cause
the thread to block, but to return a failure code instead.
Non-Blocking Synchronization
(Cont.)
What isn't promised to any thread in the following
scenario when using totalized operations?
So, how can we fix this?
Dual Data Structures

We could register a request (reservation) for a
hand-off partner.

Reservation is made in non blocking manner.

Reservation is fulfilled by checking whether a
pointer has changed in the reservation.

The structure may contain both data and
reservations.
Dual Data Structures (Cont.)
Totalized methods are now split into 2 partial
methods: reserve and follow-up.
Main advantage over totalized partial methods:
Order of reservations is saved.
Main Properties
The algorithms I will present will be:
 Contention free.
 Lock free.
 Scalable.
 Fair & unfair implementations.
 Have solid linearization points.
 Waiting is done by spinning, busy waiting.
Synchronous Dual Queue






Fair implementation.
A linked list with a head & tail.
Waiting is accomplished by spinning until a
pointer changes from null to non-null.
If not empty, has always a dummy node at the
beginning while other nodes are always of the
same type: reservation or data.
Dequeue & enqueue are symmetrical except for
the direction of the data flow.
Let’s take a look at the enqueue operation.
Synchronous Dual Queue (Cont.)

First case:
Queue is empty or contains only data. Add a new data node at the
end of the queue and spin.

Second case (interesting):
Queue contains only reservation.
First case code:
Synchronous Dual Queue (Cont.)
Second case code:
Synchronous Dual Stack

A singly linked list with only a head node.

Not fair.

Doesn’t have a dummy node at the beginning.

May contain either data or reservation nods but also
temporarily a single node of the opposite type at the
head.

Push& pop are symmetrical except for the direction of
the data flow.

Let’s take a look at the push operation.
Synchronous Dual Stack (Cont.)

First case:
Stack is empty or contains only data. Add a new data
node at the head of the stack and spin.

Second case (interesting):
Stack contains reservation at the head. Add a new data
(“fulfilling”) node at the head, find a reservation to fulfill
and remove both nodes.

Third case:
A fulfilling node at the head. Help the fulfillment
process.
First case code:
Second case code:
Third case code:
Results
Results (Cont.)
Conclusion

I presented 2 non blocking synchronous queues that
use dual data structures:
a fair and unfair version (stack & queue).

The algorithms are all lock-free.

There is little performance cost for fairness.

High scalability can be achieved by using synchronization
methods that don’t use locks.

The Algorithms are part of the Java 6 packages.