AbstractQueuedSynchronizer--基於CAS自旋volatile變數插入尾節點
阿新 • • 發佈:2018-11-28
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)中,提升了速度,設計的很精巧