基於CAS的非阻塞同步隊列的實現

基於CAS實現的組件有不少,這裏選擇非阻塞同步隊列的緣由是,當有多個線程同時添加元素時,在隊列的尾部如何利用cas保證兩個操做的原子性是有相應算法的(這兩個步驟是尾節點須要指向新增的元素,最後一個節點元素須要指向新增的元素,即新增的元素必須同時有這兩個節點指向它)。代碼以下:java

public class ConcurentQueue {node

    static class Node {
        public Object e;
        public AtomicReference<Node> nextRef ;算法

        public Node(Object e,Node next) {
            super();
            this.e = e;
            this.nextRef = new AtomicReference<Node>(next);
        }
    }
    private Node head = new Node(null,null);
    private Node tail = new Node(null,head);編程

    public void add(Object e) {
        Node new_node = new Node(e,null);//待插入節點
        while(true){
            Node curLast = tail.nextRef.get();//當前最後節點
            Node next = curLast.nextRef.get();//當前最後節點的next節點
            if(next != null){//A 若是當前最後節點的next節點不爲空,說明尾節點須要指向next節點
                tail.nextRef.compareAndSet(curLast, next);
            }else{
                if(curLast.nextRef.compareAndSet(null, new_node)){//* B 將當前最後節點的next節點設置爲新插入的節點
                    tail.nextRef.compareAndSet(curLast, new_node);//* C  將尾節點的next節點設置爲新插入的節點
                    return;
                }
            }
        }
        
    }併發

    

   public Object remove() {
        while (true) {
            Node next = head.nextRef.get();
            if (next == null) {
                return null;
            } else {
                Node nextSetNode = next.nextRef.get();
                if (head.nextRef.compareAndSet(next, nextSetNode)) {
                    return next.e;
                }
            }
        }
    }
}this

打*的兩個地方本來是須要同時成功才能保證正確性的,但根據如今瞭解的是cas只能保證一個操做的原子性,若要保證兩個操做的原子性,初看是不可能的。細心的朋友能夠看出這些代碼和java併發編程實戰中的是幾乎同樣的,也只有將head節點也做爲啞節點這一小小改動,(注意尾節點和最後一個節點是不一樣的節點),首先隊列永遠只有兩種狀態,見書中的原圖(不過描述得改爲中間態和穩定態):線程

其次隊列永遠只能在最後一個節點後面即穩定態的時候才能插入!blog

先分析一下代碼:隊列

一、當B步驟成功後,還沒來得及執行C步驟前,此時隊列就處於中間態,其他線程就會執行A步驟將尾節點推到最後一個節點上從而造成穩定態,此時再執行C步驟時儘管失敗了可是隊列已經穩定;rem

二、只要隊列不穩定時,全部的線程都會設法執行A步驟將隊列趨於穩定;

三、C步驟無論是成功仍是失敗隊列都會處於穩定狀態;

到這裏你們能夠去體會一下java併發編程實戰中說的:那兩個技巧了,說實在的沒看懂代碼前能看懂那些話麼....,還有能想到這種方法確實不容易,想一想仍是用鎖實現比較簡單明瞭。

相關文章
相關標籤/搜索