1. 程式人生 > >AbstractQueuedSynchronizer--基於CAS自旋volatile變數插入尾節點

AbstractQueuedSynchronizer--基於CAS自旋volatile變數插入尾節點

    private transient volatile Node tail;
    
      private Node enq(final Node node) {
            for (;;) {
                Node t = tail;
                if (t == null) { // Must initialize
                    if (compareAndSetHead(new Node()))
                        tail = head;
                } 
else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } }

上述程式碼是AbstractQueuedSynchronizer中關於如何往Node中新增尾節點的程式碼,使用的CAS自旋volatile

變數法,解決高併發下插入尾節點不同步問題。

1.假如尾節點為空,說明節點佇列為空,初始化一個頭結點指向尾節點的佇列;

2.繼續for迴圈,這次進入else中,先把插入節點的前置指向尾節點(這個尾節點不一定是真的尾節點,有可能在此期間被其他執行緒改變了,所以有下面的),然後進行cas操作,假如t是此時真實的尾節點,就將node改為尾節點,並將t.next指向node,然後返回。

如果compareAndSetTail(t, node)為false,說明這個尾節點不是真的尾節點,在此期間被其他執行緒改變了,故繼續自旋 ,Node t = tail 會一直將自認為的尾節點賦給t,直至compareAndSetTail

成功。

 

 

    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

 

 

 

上述addWaiter方法提供了一種快捷一點的插入節點方法,將空佇列和自旋的判斷放在enq(node)中,提升了速度,設計的很精巧