摘要:溫馨提醒隊(duì)列是隊(duì)列的變種,隊(duì)列等待采用自旋,的隊(duì)列等待采用。表示對(duì)應(yīng)線程是否應(yīng)當(dāng)阻塞,節(jié)點(diǎn)是正占有鎖的線程的,其值為,處于后驅(qū)節(jié)點(diǎn)的線程才會(huì)去,由子類實(shí)現(xiàn)。
溫馨提醒
AbstractQueuedSynchronizer隊(duì)列是CLH隊(duì)列的變種,CLH隊(duì)列等待采用自旋,AQS的隊(duì)列等待采用LockSupport#park。
Node.waitStatus表示對(duì)應(yīng)線程是否應(yīng)當(dāng)阻塞,
head節(jié)點(diǎn)是正占有鎖的線程的,其thread值為null,處于head后驅(qū)節(jié)點(diǎn)的線程才會(huì)去tryAcquire,tryAcquire由子類實(shí)現(xiàn)。
入隊(duì)在tail,出隊(duì)在head
以下必須要子類實(shí)現(xiàn): /** * 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()獨(dú)占模式acquire
private Node enq(final Node node) { // 無(wú)限循環(huán),即step 1返回false(有別的線程將它的node連接到tail)也會(huì)重新將node連接到tail for (;;) { Node t = tail; if (t == null) { // new一個(gè)不帶任何狀態(tài)的Node作為頭節(jié)點(diǎn) if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { // step 1 t.next = node; return t; // 返回當(dāng)前tail } } } } private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); //-- 和#enq邏輯比,只是取消了循環(huán),為了更快? Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } //-- enq(node); return node; // 返回當(dāng)前線程的node } final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; // 無(wú)限循環(huán),直到當(dāng)前線程node的前驅(qū)node是head,否則對(duì)于node狀態(tài)為SIGNAL的線程會(huì)park for (;;) { final Node p = node.predecessor(); // 如果當(dāng)前線程node的前驅(qū)是head if (p == head && tryAcquire(arg)) { // head = node; 從而讓其他線程也能走入該if // node.thread = null; 所以head永遠(yuǎn)是一個(gè)不帶Thread的空節(jié)點(diǎn) // node.prev = null; setHead(node); p.next = null; // 配合上面的 node.prev = null; for GC failed = false; return interrupted; } // 判斷在tryAcquire失敗后是否應(yīng)該park,若是,則執(zhí)行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; // 表示當(dāng)前節(jié)點(diǎn)應(yīng)當(dāng)park if (ws == Node.SIGNAL) return true; // 當(dāng)前節(jié)點(diǎn)不斷向前找,直到找到一個(gè)前驅(qū)節(jié)點(diǎn)waitStats不是CANCELLED的為止(狀態(tài)值里面只有CANCELLED是大于0的) if (ws > 0) { do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); // 中間CANCELLED的node作廢 pred.next = node; } // 0 or PROPAGATE 需要設(shè)置為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為了省去入隊(duì)列操作,提高性能,因?yàn)榇蟛糠智闆r下可能都沒(méi)有鎖競(jìng)爭(zhēng) if (!tryAcquire(arg) && // 入隊(duì)列,返回當(dāng)前線程中斷狀態(tài) acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }獨(dú)占模式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設(shè)為0,是為了不重復(fù)step 1 if (ws < 0) compareAndSetWaitStatus(node, ws, 0); Node s = node.next; // 如果head(當(dāng)前線程)無(wú)后驅(qū)node,或后驅(qū)node為CANCELLED if (s == null || s.waitStatus > 0) { s = null; // 從鏈表tail開(kāi)始遍歷,取出非CANCELLED的node for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } // 非CANCELLED的線程unpark,繼續(xù)#acquireQueued的for循環(huán) if (s != null) LockSupport.unpark(s.thread); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76325.html
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢?jiàn)它的使用,在開(kāi)始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽(tīng)名字多牛逼,來(lái),我們一步一步來(lái)?yè)羝魄皟蓚€(gè)名詞,今天我們首先來(lái)說(shuō)說(shuō)分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢?jiàn)它的使用,在開(kāi)始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽(tīng)名字多牛逼,來(lái),我們一步一步來(lái)?yè)羝魄皟蓚€(gè)名詞,今天我們首先來(lái)說(shuō)說(shuō)分布式。 探究...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)??梢?jiàn)它的使用,在開(kāi)始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽(tīng)名字多牛逼,來(lái),我們一步一步來(lái)?yè)羝魄皟蓚€(gè)名詞,今天我們首先來(lái)說(shuō)說(shuō)分布式。 探究...
摘要:溫馨提醒隊(duì)列是隊(duì)列的變種,隊(duì)列等待采用自旋,的隊(duì)列等待采用。表示對(duì)應(yīng)線程是否應(yīng)當(dāng)阻塞,節(jié)點(diǎn)是正占有鎖的線程的,其值為,處于后驅(qū)節(jié)點(diǎn)的線程才會(huì)去,由子類實(shí)現(xiàn)。 溫馨提醒 AbstractQueuedSynchronizer隊(duì)列是CLH隊(duì)列的變種,CLH隊(duì)列等待采用自旋,AQS的隊(duì)列等待采用LockSupport#park。 Node.waitStatus表示對(duì)應(yīng)線程是否應(yīng)當(dāng)阻塞, he...
摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類的相關(guān)原理,java.util.concurrent包中很多類都依賴于這個(gè)類所提供的隊(duì)列式...
閱讀 2073·2021-09-22 15:43
閱讀 8747·2021-09-22 15:07
閱讀 1088·2021-09-03 10:28
閱讀 2063·2021-08-19 10:57
閱讀 1077·2020-01-08 12:18
閱讀 2982·2019-08-29 15:09
閱讀 1534·2019-08-29 14:05
閱讀 1647·2019-08-29 13:57