Skip to content

Instantly share code, notes, and snippets.

@tomtzook
Last active May 14, 2020 04:06
Show Gist options
  • Save tomtzook/81d7151ab97d05219911a593caca01ab to your computer and use it in GitHub Desktop.
Save tomtzook/81d7151ab97d05219911a593caca01ab to your computer and use it in GitHub Desktop.
Basic lock-free queue in Java
import java.util.concurrent.atomic.AtomicReference;
public class LockFreeQueue<T> {
private final AtomicReference<Node<T>> mHead;
private final AtomicReference<Node<T>> mLast;
public LockFreeQueue() {
Node<T> baseNode = new Node<>(null);
mHead = new AtomicReference<>(baseNode);
mLast = new AtomicReference<>(baseNode);
}
public void enqueue(T value) {
Node<T> node = new Node<>(value);
Node<T> lastHead = mHead.get();
while (!mHead.compareAndSet(lastHead, node)) {
lastHead = mHead.get();
}
node.setNext(lastHead);
lastHead.setPrevious(node);
}
public T dequeue() {
Node<T> last = mLast.get();
if (last == mHead.get()) {
return null;
}
Node<T> previous = last.getPrevious();
while (!mLast.compareAndSet(last, previous)) {
previous = last.getPrevious();
}
previous.setNext(null);
return previous.getValue();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Node<T> node = mHead.get();
Node<T> last = mLast.get();
while (node != last) {
builder.append(node);
builder.append("->");
node = node.getNext();
}
return builder.toString();
}
}
class Node<T> {
private final T mValue;
private volatile Node<T> mNext;
private volatile Node<T> mPrevious;
Node(T value) {
mValue = value;
}
public T getValue() {
return mValue;
}
public Node<T> getNext() {
return mNext;
}
public void setNext(Node<T> next) {
mNext = next;
}
public Node<T> getPrevious() {
return mPrevious;
}
public void setPrevious(Node<T> previous) {
mPrevious = previous;
}
@Override
public String toString() {
return mValue.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment