ConcurrentLinkedQueue詳解


ConcurrentLinkedQueue詳解

簡介

實現線程安全的隊列的兩種方式:

  1. 使用阻塞算法:對入隊和出隊使用同一把鎖(或不同的鎖).
  2. 使用非阻塞算法:使用循環CAS方式實現.
  • ConcurrentLinkedQueue是一個基於鏈接節點的無界線程安全隊列.
  • 采用先進先出規則對節點排序.
  • 添加元素會添加到隊列的尾部,獲取元素會返回隊列頭部元素.

結構

  • 有兩個結點:頭節點(head)和尾節點(tail).
  • 每個節點由結點元素(item)和指向下一個節點的指針(next)組成.
  • 默認情況下head節點存儲的元素為空,tail節點等於head節點.

操作

入隊列

將入隊節點添加到隊列尾部.

public boolean offer(E e) {
    checkNotNull(e);
    final Node<E> newNode = new Node<E>(e);

    for (Node<E> t = tail, p = t;;) {
        Node<E> q = p.next;
        if (q == null) {
            if (p.casNext(null, newNode)) {
                if (p != t)
                    casTail(t, newNode);
                return true;
            }
        }
        else if (p == q)
            p = (t != (t = tail)) ? t : head;
        else
            p = (p != t && t != (t = tail)) ? t : q;
    }
}

流程:

  1. 定位尾節點.
  2. 使用CAS將入隊節點設置為尾節點的next節點,若不成功,則重試.

定位尾節點:
tail節點並非總是尾節點.每次入隊必須先通過tail節點查找尾節點.

設置入隊節點為尾節點:
設置入隊節點為當前尾節點的next節點.

  • 剛開始head和tail節點都指向空節點.
  • 添加一個節點后,head和tail仍然指向空節點.
  • 再添加節點時,head指向空節點,tail指向尾節點.
  • 再次添加節點時,tail保持不變.
  • 再添加結點時,tail指向尾節點.

出隊列

出隊列是從隊列中返回一個節點元素.

public E poll() {
    restartFromHead:
    for (;;) {
        for (Node<E> h = head, p = h, q;;) {
            E item = p.item;

            if (item != null && p.casItem(item, null)) {
                if (p != h)
                    updateHead(h, ((q = p.next) != null) ? q : p);
                return item;
            }
            else if ((q = p.next) == null) {
                updateHead(h, p);
                return null;
            }
            else if (p == q)
                continue restartFromHead;
            else
                p = q;
        }
    }
}

流程:

  • 當head節點有元素時,直接彈出head節點對應的元素,不更新head節點.
  • 當head節點沒有元素時,出隊操作更新head節點.

目的:減少使用CAS更新head節點的消耗,提高效率.

  • 先獲取頭節點的元素.
  • 再判斷頭節點元素是否為空.如果為空,則另外一個線程已進行出隊操作.
  • 若不為空,則使用CAS方式將頭節點的引用設為null.成功則直接返回頭節點元素;不成功則其他線程已進行出隊操作更新head節點,需重新獲取頭節點.

參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM