CAS 实现 NonBlocking-ConcurrencyQueue

先列出完整代码:

public class LinkedQueue<E> {

	private static class Node<E>{
		final E item;
		final AtomicReference<Node<E>> next = new AtomicReference<Node<E>>();
		
		public Node(E item, Node<E> next){
			this.item = item;
			this.next.set(next);;
		}
	}
	
	private final Node<E> dummy = new Node<E>(null, null);
	
	private final AtomicReference<Node<E>> head = new AtomicReference<Node<E>>(dummy);
	
	private final AtomicReference<Node<E>> tail = new AtomicReference<Node<E>>(dummy);
	
	public boolean put(E item){
		Node<E> newNode = new Node<E>(item, null);
		for(;;){
			Node<E> curTail = tail.get();
			Node<E> tailNext = curTail.next.get();
			if(curTail == tail.get()){
				if(tailNext != null){
					tail.compareAndSet(curTail, tailNext);
				}else{
					if(curTail.next.compareAndSet(null, newNode)){
						tail.compareAndSet(curTail, newNode);
						return true;
					}
				}
			}
		}
	}
	
	public E poll(){
		Node<E> oldHead=null;
		Node<E> headNext = null;
		Node<E> tailNow = null;
		Node<E> tailNext = null;
		for(;;){
			oldHead = head.get();
			headNext = oldHead.next.get();
			tailNow = tail.get();
			tailNext = tailNow.next.get();
			if(oldHead == tailNow && headNext == tailNext){
				if(tailNext != null){
					tail.compareAndSet(tailNow, tailNext);
				}else if(oldHead.item != null){
					Node<E> newNode = new Node<E>(null, null);
					tailNow.next.compareAndSet(null, newNode);
				}else{
					return null;
				}
				
			}else if(oldHead == tailNow && headNext != tailNext){
			}else{
				if(headNext ==null){	// should not happen deal with unexpected events
					continue;
				}
				if(head.compareAndSet(oldHead, headNext)){
					if(oldHead.item == null)
						continue;
					return oldHead.item;
				}
			}
		}
		
	}
}

对 put(E e) 方法的解释看下面这里:

http://www.ibm.com/developerworks/cn/java/j-jtp04186/

这里只对 poll() 解释:

初始状态为 state1:

最初当有线程在 put 之前调用 poll 时 queue 保持 state1 并返回 null;

当有线程调用 put 后 queue 在 state3 or state4;

此时有线程调用 poll 时 queue 由 state3 -> state4 -> state2 or state4 -> state2;

在有线程调用 poll 时 queue 由 state2 -> state3;

CAS 实现 NonBlocking-ConcurrencyQueue_第1张图片CAS 实现 NonBlocking-ConcurrencyQueue_第2张图片CAS 实现 NonBlocking-ConcurrencyQueue_第3张图片CAS 实现 NonBlocking-ConcurrencyQueue_第4张图片

状态转换:

CAS 实现 NonBlocking-ConcurrencyQueue_第5张图片

我认为状态转换是这样的,可是实际上出现了意外的情况

else if(oldHead == tailNow && headNext != tailNext){
}else{
    if(headNext ==null){	// should not happen deal with unexpected state
        continue;
    }
}

理想情况应该不会出现oldHead == tailNow 而 headNext!= tailNext 的情况

因为 oldHead的值是在tailNow后取得,且我查看了该类的字节码他们的运行顺序并没有置换

且理想情况下也不会出现 headNext == null 的情况。

实际测试上述两种情况都有出现。

出现 意外的状态,只好循环直到状态恢复正常。

希望有人可以为我解一下惑(怀疑是cpu cache 或 register 暂存导致的,可是 Node 属性已经 final 了)


相关代码(测试代码),里面有一些多余的代码,忽略即可

链接: http://pan.baidu.com/s/1dDnbWgp 密码: qmba









你可能感兴趣的:(cas,NonBlocking)