Created
March 13, 2020 16:41
-
-
Save vladimir-bukhtoyarov/4feeec9d0bd17fa7718cd90834d5080d to your computer and use it in GitHub Desktop.
An example of classic Michael-Scott queue implementation in java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.concurrent.atomic.AtomicReference; | |
/** | |
* An example of classic Michael-Scott queue | |
* | |
* @param <T> | |
*/ | |
public class MSQueue<T> { | |
private final class Node<T> { | |
// TODO it could be replaced by AtomicFieldUpdater in order to reduce memory footprint, | |
// but I especially avoided to do this because intent of MSQueue is just to be a learning eaxample | |
private final AtomicReference<Node<T>> nextRef; | |
private T item; | |
private Node(T item, Node<T> next) { | |
this.nextRef = new AtomicReference<>(next); | |
this.item = item; | |
} | |
} | |
private final AtomicReference<Node<T>> tailRef = new AtomicReference<>(new Node<>(null, null)); | |
private final AtomicReference<Node<T>> headRef = new AtomicReference<>(tailRef.get()); | |
public final void put(T item) { | |
Node<T> newNode = new Node<T>(item, null); | |
while (true) { | |
Node<T> currentTail = tailRef.get(); | |
Node<T> nextTail = currentTail.nextRef.get(); | |
if (currentTail == tailRef.get()) { | |
if (nextTail != null) { | |
tailRef.compareAndSet(currentTail, nextTail); | |
} else { | |
if (currentTail.nextRef.compareAndSet(null, newNode)) { | |
tailRef.compareAndSet(currentTail, newNode); | |
return; | |
} | |
} | |
} | |
} | |
} | |
public final T poll() { | |
while (true) { | |
Node<T> currentHead = headRef.get(); | |
Node<T> currentTail = tailRef.get(); | |
Node<T> next = currentHead.nextRef.get(); | |
if (currentHead == headRef.get()) { | |
if (currentHead == currentTail) { | |
if (next == null) { | |
return null; | |
} else { | |
// help to producer | |
tailRef.compareAndSet(currentTail, next); | |
} | |
} else { | |
if (headRef.compareAndSet(currentHead, next)) { | |
T item = next.item; | |
next.item = null; // help to gc | |
return item; | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment