Non-Blocking Concurrent Queue with offer and flush
I'd need an unbounded non-blocking concurrent queue with basically only 2 operations:
The goal is the consumer has a single CAS operation on the takeAll and can then iterate the elements in the list without going through a CAS operation per read. Further we already own the Node (Entry) as this is needed to store some other immutable state. The new node can take the HEAD as a constructor argument, creating a single direction linked list.
Does exist in literature a queue with these characteristics?
Unlike a LinkedBlockingQueue, a ConcurrentLinkedQueue is a non-blocking queue. Thus, it does not block a thread once the queue is empty. Instead, it returns null. Since its unbounded, it'll throw a java.
Blocking vs Non-Blocking QueueThe producers will wait for available capacity before adding elements, while consumers will wait until the queue is empty. In those cases, the non-blocking queue will either throw an exception or return a special value, like null or false.
An unbounded thread-safe queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time.
Concurrent Queue. A concurrent queue is basically a queue which provides protection against multiple threads mutating its state and thus causing inconsistencies. A naive way to implement a concurrent queue may be to just slap locks in its enqueue and dequeue functions when they try to modify the head and tail.
Here you go:
public class FunkyQueue<T> {
private final AtomicReference<Node<T>> _tail = new AtomicReference<Node<T>>();
public void offer(T t) {
while(true) {
Node<T> tail = _tail.get();
Node<T> newTail = new Node<T>(t, tail);
if(_tail.compareAndSet(tail, newTail)) {
break;
}
}
}
public List<T> takeAll() {
Node<T> tail = _tail.getAndSet(null);
LinkedList<T> list = new LinkedList<T>();
while(tail != null) {
list.addFirst(tail.get());
tail = tail.getPrevious();
}
return list;
}
private static final class Node<T>
{
private final T _obj;
private Node<T> _prev;
private Node(T obj, Node<T> prev) {
_obj = obj;
_prev = prev;
}
public T get() {
return _obj;
}
public Node<T> getPrevious() {
return _prev;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With