Lock Free Stack
This example is copied from book "Java Concurrency in Practice".
From this example we can learn that the lock free queue code is not correct for MPMC (multi-producer-multi-consumer) in my previous post.
Actually, lock free means you should guarantee the atomicity of updating a pointer. When you add a new node on top of current stack top, the top node might be poped by another thread. So you should prepare to do that again if that did happen. How to do this? We thus need a CAS operation, if current top is what we saw and we have successfully update the top to a new node, ok, our job is done.
While, lock free queue can be more complicated if you insert one node to the tail since we need to update two pointers at same time, one is a *tail* pointing to the last node and one is its *next* pointer.
I will give one correct queue code in the next post.
From this example we can learn that the lock free queue code is not correct for MPMC (multi-producer-multi-consumer) in my previous post.
Actually, lock free means you should guarantee the atomicity of updating a pointer. When you add a new node on top of current stack top, the top node might be poped by another thread. So you should prepare to do that again if that did happen. How to do this? We thus need a CAS operation, if current top is what we saw and we have successfully update the top to a new node, ok, our job is done.
While, lock free queue can be more complicated if you insert one node to the tail since we need to update two pointers at same time, one is a *tail* pointing to the last node and one is its *next* pointer.
I will give one correct queue code in the next post.
@ThreadSafe
public class ConcurrentStack <E> {
AtomicReference<Node<E>> top = new AtomicReference<Node<E>>();
public void push(E item) {
Node<E> newHead = new Node<E>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
public E pop() {
Node<E> oldHead;
Node<E> newHead;
do {
oldHead = top.get();
if (oldHead == null)
return null;
newHead = oldHead.next;
} while (!top.compareAndSet(oldHead, newHead));
return oldHead.item;
}
private static class Node <E> {
public final E item;
public Node<E> next;
public Node(E item) {
this.item = item;
}
}
}