Treiber Stack Algorithm是一個可擴展的無鎖棧,利用細粒度的併發原語CAS來實現的,Treiber Stack在 R. Kent Treiber在1986年的論文Systems Programming: Coping with Parallelism中首次出現。算法
該算法的基本原理是:只有當您知道要添加的項目是自開始操做以來惟一添加的項目時,纔會添加新的項目。 這是經過使用比較和交換完成的。 在添加新項目時使用堆棧,將堆棧的頂部放在新項目以後。 而後,將這個新構造的頭元素(舊頭)的第二個項目與當前項目進行比較。 若是二者匹配,那麼你能夠將舊頭換成新頭,不然就意味着另外一個線程已經向堆棧添加了另外一個項目,在這種狀況下,你必須再試一次。數據結構
當從堆棧中彈出一個項目時,在返回項目以前,您必須檢查另外一個線程自操做開始以來沒有添加其餘項目。併發
在某些語言中,特別是那些沒有垃圾回收的語言,Treiber棧可能面臨ABA問題。當一個進程要從堆棧中移除一個元素時(就在下面的pop例程比較和設置以前),另外一個進程能夠改變堆棧,使得頭部是相同的,可是第二個元素是不一樣的。比較和交換將堆棧的頭部設置爲堆棧中舊的第二個元素,混合完整的數據結構。可是,因爲Java運行時提供了更強大的保證,因此此頁面上的Java版本不受此問題的影響(新建立的不混淆的對象引用不可能與任何其餘可到達的對象引用相同)。測試
對諸如ABA之類的故障進行測試可能會很是困難,由於有問題的事件序列很是少見。this
下面是Java中Treiber Stack的實現,它基於Java Concurrency in Practice提供的spa
public class ConcurrentStack<E> { private AtomicReference<Node<E>> top = new AtomicReference<>(); public void push(E item) { Node<E> newHead = new Node<>(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; } } }
根據上述的描述作圖如上,並分析其工做流程。線程
newHead
,並讓該新節點的next
指針指向top
節點(此時top=oldHead
)。top=newHead
,CAS的交換條件是top=oldHead
。
根據上述的描述作圖如上,並分析其工做流程。指針
top
的next
元素。top=newHead
,CAS的交換條件是top=oldHead
。3.當條件知足後,操做後的狀態以下:
參考:https://en.wikipedia.org/wiki...code