摘要:溫馨提醒隊列是隊列的變種,隊列等待采用自旋,的隊列等待采用。表示對應線程是否應當阻塞,節點是正占有鎖的線程的,其值為,處于后驅節點的線程才會去,由子類實現。
溫馨提醒
AbstractQueuedSynchronizer隊列是CLH隊列的變種,CLH隊列等待采用自旋,AQS的隊列等待采用LockSupport#park。
Node.waitStatus表示對應線程是否應當阻塞,
head節點是正占有鎖的線程的,其thread值為null,處于head后驅節點的線程才會去tryAcquire,tryAcquire由子類實現。
入隊在tail,出隊在head
以下必須要子類實現: /** * exclusive mode */ boolean tryAcquire(int arg) /** * exclusive mode. */ boolean tryRelease(int arg) /** * shared mode. */ int tryAcquireShared(int arg) /** * shared mode. */ boolean tryReleaseShared(int arg) /** * Returns true if synchronization is held exclusively with * respect to the current (calling) thread. */ boolean isHeldExclusively()獨占模式acquire
private Node enq(final Node node) { // 無限循環,即step 1返回false(有別的線程將它的node連接到tail)也會重新將node連接到tail for (;;) { Node t = tail; if (t == null) { // new一個不帶任何狀態的Node作為頭節點 if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { // step 1 t.next = node; return t; // 返回當前tail } } } } private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); //-- 和#enq邏輯比,只是取消了循環,為了更快? Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } //-- enq(node); return node; // 返回當前線程的node } final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; // 無限循環,直到當前線程node的前驅node是head,否則對于node狀態為SIGNAL的線程會park for (;;) { final Node p = node.predecessor(); // 如果當前線程node的前驅是head if (p == head && tryAcquire(arg)) { // head = node; 從而讓其他線程也能走入該if // node.thread = null; 所以head永遠是一個不帶Thread的空節點 // node.prev = null; setHead(node); p.next = null; // 配合上面的 node.prev = null; for GC failed = false; return interrupted; } // 判斷在tryAcquire失敗后是否應該park,若是,則執行park if (shouldParkAfterFailedAcquire(p, node) && // LockSupport#park,返回Thread#interrupted parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; // 表示當前節點應當park if (ws == Node.SIGNAL) return true; // 當前節點不斷向前找,直到找到一個前驅節點waitStats不是CANCELLED的為止(狀態值里面只有CANCELLED是大于0的) if (ws > 0) { do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); // 中間CANCELLED的node作廢 pred.next = node; } // 0 or PROPAGATE 需要設置為SIGNAL,但仍然返回false,即don’t park else { compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; } // Acquires in exclusive mode, ignoring interrupts public final void acquire(int arg) { // 這里提前tryAcquire為了省去入隊列操作,提高性能,因為大部分情況下可能都沒有鎖競爭 if (!tryAcquire(arg) && // 入隊列,返回當前線程中斷狀態 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }獨占模式release
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) // step 1 unparkSuccessor(h); return true; } return false; } private void unparkSuccessor(Node node) { int ws = node.waitStatus; // 這里是SIGNAL,將head的waitStatus設為0,是為了不重復step 1 if (ws < 0) compareAndSetWaitStatus(node, ws, 0); Node s = node.next; // 如果head(當前線程)無后驅node,或后驅node為CANCELLED if (s == null || s.waitStatus > 0) { s = null; // 從鏈表tail開始遍歷,取出非CANCELLED的node for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } // 非CANCELLED的線程unpark,繼續#acquireQueued的for循環 if (s != null) LockSupport.unpark(s.thread); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68616.html
摘要:表示的是兩個,當其中任意一個計算完并發編程之是線程安全并且高效的,在并發編程中經常可見它的使用,在開始分析它的高并發實現機制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購,是兩個比較典型的互聯網高并發場景。 干貨:深度剖析分布式搜索引擎設計 分布式,高可用,和機器學習一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來擊破前兩個名詞,今天我們首先來說說分布式。 探究...
摘要:溫馨提醒隊列是隊列的變種,隊列等待采用自旋,的隊列等待采用。表示對應線程是否應當阻塞,節點是正占有鎖的線程的,其值為,處于后驅節點的線程才會去,由子類實現。 溫馨提醒 AbstractQueuedSynchronizer隊列是CLH隊列的變種,CLH隊列等待采用自旋,AQS的隊列等待采用LockSupport#park。 Node.waitStatus表示對應線程是否應當阻塞, he...
摘要:在中一般來說通過來創建所需要的線程池,如高并發原理初探后端掘金閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。 AbstractQueuedSynchronizer 超詳細原理解析 - 后端 - 掘金今天我們來研究學習一下AbstractQueuedSynchronizer類的相關原理,java.util.concurrent包中很多類都依賴于這個類所提供的隊列式...
閱讀 7627·2023-04-25 14:36
閱讀 1753·2021-11-22 09:34
閱讀 2146·2019-08-30 15:55
閱讀 3144·2019-08-30 11:19
閱讀 1305·2019-08-29 15:17
閱讀 548·2019-08-29 12:47
閱讀 2990·2019-08-26 13:38
閱讀 2625·2019-08-26 11:00