成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

J.U.C|同步隊(duì)列(CLH)

Nosee / 2197人閱讀

摘要:二什么是同步隊(duì)列同步隊(duì)列一個(gè)雙向隊(duì)列,隊(duì)列中每個(gè)節(jié)點(diǎn)等待前驅(qū)節(jié)點(diǎn)釋放共享狀態(tài)鎖被喚醒就可以了。三入列操作如上圖了解了同步隊(duì)列的結(jié)構(gòu),我們?cè)诜治銎淙肓胁僮髟诤?jiǎn)單不過(guò)。

一、寫(xiě)在前面

在上篇我們聊到AQS的原理,具體參見(jiàn)《J.U.C|AQS原理》。

這篇我們來(lái)給大家聊聊AQS中核心同步隊(duì)列(CLH)。

二、什么是同步隊(duì)列(CLH)

同步隊(duì)列

一個(gè)FIFO雙向隊(duì)列,隊(duì)列中每個(gè)節(jié)點(diǎn)等待前驅(qū)節(jié)點(diǎn)釋放共享狀態(tài)(鎖)被喚醒就可以了。

AQS如何使用它?

AQS依賴(lài)它來(lái)完成同步狀態(tài)的管理,當(dāng)前線(xiàn)程如果獲取同步狀態(tài)失敗時(shí),AQS則會(huì)將當(dāng)前線(xiàn)程已經(jīng)等待狀態(tài)等信息構(gòu)造成一個(gè)節(jié)點(diǎn)(Node)并將其加入到CLH同步隊(duì)列,同時(shí)會(huì)阻塞當(dāng)前線(xiàn)程,當(dāng)同步狀態(tài)釋放時(shí),會(huì)把首節(jié)點(diǎn)喚醒(公平鎖),使其再次嘗試獲取同步狀態(tài)。

Node節(jié)點(diǎn)面貌?

static final class Node {
        // 節(jié)點(diǎn)分為兩種模式: 共享式和獨(dú)占式
        /** 共享式 */
        static final Node SHARED = new Node();
        /** 獨(dú)占式 */
        static final Node EXCLUSIVE = null;

        /** 等待線(xiàn)程超時(shí)或者被中斷、需要從同步隊(duì)列中取消等待(也就是放棄資源的競(jìng)爭(zhēng)),此狀態(tài)不會(huì)在改變 */
        static final int CANCELLED =  1;
        /** 后繼節(jié)點(diǎn)會(huì)處于等待狀態(tài),當(dāng)前節(jié)點(diǎn)線(xiàn)程如果釋放同步狀態(tài)或者被取消則會(huì)通知后繼節(jié)點(diǎn)線(xiàn)程,使后繼節(jié)點(diǎn)線(xiàn)程的得以運(yùn)行 */
        static final int SIGNAL    = -1;
        /** 節(jié)點(diǎn)在等待隊(duì)列中,線(xiàn)程在等待在Condition 上,其他線(xiàn)程對(duì)Condition調(diào)用singnal()方法后,該節(jié)點(diǎn)加入到同步隊(duì)列中。 */
        static final int CONDITION = -2;
        /**
         * 表示下一次共享式獲取同步狀態(tài)的時(shí)會(huì)被無(wú)條件的傳播下去。
         */
        static final int PROPAGATE = -3;

        /**等待狀態(tài)*/
        volatile int waitStatus;

        /**前驅(qū)節(jié)點(diǎn) */
        volatile Node prev;

        /**后繼節(jié)點(diǎn)*/
        volatile Node next;

        /**獲取同步狀態(tài)的線(xiàn)程 */
        volatile Thread thread;

        /**鏈接下一個(gè)等待狀態(tài) */
        Node nextWaiter;
        
        // 下面一些方法就不貼了
    }

CLH同步隊(duì)列的結(jié)構(gòu)圖

這里是基于CAS(保證線(xiàn)程的安全)來(lái)設(shè)置尾節(jié)點(diǎn)的。

三、入列操作

如上圖了解了同步隊(duì)列的結(jié)構(gòu), 我們?cè)诜治銎淙肓胁僮髟诤?jiǎn)單不過(guò)。無(wú)非就是將tail(使用CAS保證原子操作)指向新節(jié)點(diǎn),新節(jié)點(diǎn)的prev指向隊(duì)列中最后一節(jié)點(diǎn)(舊的tail節(jié)點(diǎn)),原隊(duì)列中最后一節(jié)點(diǎn)的next節(jié)點(diǎn)指向新節(jié)點(diǎn)以此來(lái)建立聯(lián)系,來(lái)張圖幫助大家理解。

源碼
源碼我們可以通過(guò)AQS中的以下兩個(gè)方法來(lái)了解下
addWaiter方法

private Node addWaiter(Node mode) {
// 以給定的模式來(lái)構(gòu)建節(jié)點(diǎn), mode有兩種模式 
//  共享式SHARED, 獨(dú)占式EXCLUSIVE;
  Node node = new Node(Thread.currentThread(), mode);
    // 嘗試快速將該節(jié)點(diǎn)加入到隊(duì)列的尾部
    Node pred = tail;
     if (pred != null) {
        node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        // 如果快速加入失敗,則通過(guò) anq方式入列
        enq(node);
        return node;
    }

先通過(guò)addWaiter(Node node)方法嘗試快速將該節(jié)點(diǎn)設(shè)置尾成尾節(jié)點(diǎn),設(shè)置失敗走enq(final Node node)方法

enq

private Node enq(final Node node) {
// CAS自旋,直到加入隊(duì)尾成功        
for (;;) {
    Node t = tail;
        if (t == null) { // 如果隊(duì)列為空,則必須先初始化CLH隊(duì)列,新建一個(gè)空節(jié)點(diǎn)標(biāo)識(shí)作為Hader節(jié)點(diǎn),并將tail 指向它
            if (compareAndSetHead(new Node()))
                tail = head;
            } else {// 正常流程,加入隊(duì)列尾部
                node.prev = t;
                    if (compareAndSetTail(t, node)) {
                        t.next = node;
                        return t;
                }
            }
        }
    }

通過(guò)“自旋”也就是死循環(huán)的方式來(lái)保證該節(jié)點(diǎn)能順利的加入到隊(duì)列尾部,只有加入成功才會(huì)退出循環(huán),否則會(huì)一直循序直到成功。

上述兩個(gè)方法都是通過(guò)compareAndSetHead(new Node())方法來(lái)設(shè)置尾節(jié)點(diǎn),以保證節(jié)點(diǎn)的添加的原子性(保證節(jié)點(diǎn)的添加的線(xiàn)程安全。)

四、出列操作

同步隊(duì)列(CLH)遵循FIFO,首節(jié)點(diǎn)是獲取同步狀態(tài)的節(jié)點(diǎn),首節(jié)點(diǎn)的線(xiàn)程釋放同步狀態(tài)后,將會(huì)喚醒它的后繼節(jié)點(diǎn)(next),而后繼節(jié)點(diǎn)將會(huì)在獲取同步狀態(tài)成功時(shí)將自己設(shè)置為首節(jié)點(diǎn),這個(gè)過(guò)程非常簡(jiǎn)單。如下圖

設(shè)置首節(jié)點(diǎn)是通過(guò)獲取同步狀態(tài)成功的線(xiàn)程來(lái)完成的(獲取同步狀態(tài)是通過(guò)CAS來(lái)完成),只能有一個(gè)線(xiàn)程能夠獲取到同步狀態(tài),因此設(shè)置頭節(jié)點(diǎn)的操作并不需要CAS來(lái)保證,只需要將首節(jié)點(diǎn)設(shè)置為其原首節(jié)點(diǎn)的后繼節(jié)點(diǎn)并斷開(kāi)原首節(jié)點(diǎn)的next(等待GC回收)應(yīng)用即可。

五、總結(jié)

聊完后我們來(lái)總一下,同步隊(duì)列就是一個(gè)FIFO雙向?qū)﹃?duì)列,其每個(gè)節(jié)點(diǎn)包含獲取同步狀態(tài)失敗的線(xiàn)程應(yīng)用、等待狀態(tài)、前驅(qū)節(jié)點(diǎn)、后繼節(jié)點(diǎn)、節(jié)點(diǎn)的屬性類(lèi)型以及名稱(chēng)描述。

其入列操作也就是利用CAS(保證線(xiàn)程安全)來(lái)設(shè)置尾節(jié)點(diǎn),出列就很簡(jiǎn)單了直接將head指向新頭節(jié)點(diǎn)并斷開(kāi)老頭節(jié)點(diǎn)聯(lián)系就可以了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/74241.html

相關(guān)文章

  • J.U.C|condition分析

    摘要:造成當(dāng)前線(xiàn)程在接到信號(hào)被中斷或到達(dá)指定最后期限之前一直處于等待狀態(tài)。該線(xiàn)程從等待方法返回前必須獲得與相關(guān)的鎖。如果線(xiàn)程已經(jīng)獲取了鎖,則將喚醒條件隊(duì)列的首節(jié)點(diǎn)。 一、寫(xiě)在前面 在前幾篇我們聊了 AQS、CLH、ReentrantLock、ReentrantReadWriteLock等的原理以及其源碼解讀,具體參見(jiàn)專(zhuān)欄 《非學(xué)無(wú)以廣才》 這章我們一起聊聊顯示的Condition 對(duì)象。 ...

    Sourcelink 評(píng)論0 收藏0
  • J.U.C|AQS獨(dú)占式源碼分析

    摘要:本章我們主要聊獨(dú)占式即同一時(shí)刻只能有一個(gè)線(xiàn)程獲取同步狀態(tài),其它獲取同步狀態(tài)失敗的線(xiàn)程則會(huì)加入到同步隊(duì)列中進(jìn)行等待。到這獨(dú)占式獲取同步和釋放同步狀態(tài)的源碼已經(jīng)分析完了。 一、寫(xiě)在前面 上篇文章通過(guò)ReentrantLock 的加鎖和釋放鎖過(guò)程給大家聊了聊AQS架構(gòu)以及實(shí)現(xiàn)原理,具體參見(jiàn)《J.U.C|AQS的原理》。 理解了原理,我們?cè)趤?lái)看看再來(lái)一步一步的聊聊其源碼是如何實(shí)現(xiàn)的。 本章給...

    why_rookie 評(píng)論0 收藏0
  • J.U.C|一文搞懂AQS

    摘要:接著線(xiàn)程過(guò)來(lái)通過(guò)方式獲取鎖,獲取鎖的過(guò)程就是通過(guò)操作變量將其值從變?yōu)椤>€(xiàn)程加鎖成功后還有一步重要的操作,就是將設(shè)置成為自己。線(xiàn)程屁顛屁顛的就去等待區(qū)小憩一會(huì)去了。 一、寫(xiě)在前面 這篇文章,我們聊一聊Java并發(fā)中的核武器, AQS底層實(shí)現(xiàn)。 不管是工作三四年、還是五六年的在工作或者面試中涉及到并發(fā)的是時(shí)候總是繞不過(guò)AQS這個(gè)詞。 首先,確實(shí)還有很多人連AQS是什么都不知道,甚至有的竟...

    tommego 評(píng)論0 收藏0
  • J.U.C|可重入鎖ReentrantLock

    摘要:二什么是重入鎖可重入鎖,顧名思義,支持重新進(jìn)入的鎖,其表示該鎖能支持一個(gè)線(xiàn)程對(duì)資源的重復(fù)加鎖。將由最近成功獲得鎖,并且還沒(méi)有釋放該鎖的線(xiàn)程所擁有??梢允褂煤头椒▉?lái)檢查此情況是否發(fā)生。 一、寫(xiě)在前面 前幾篇我們具體的聊了AQS原理以及底層源碼的實(shí)現(xiàn),具體參見(jiàn) 《J.U.C|一文搞懂AQS》《J.U.C|同步隊(duì)列(CLH)》《J.U.C|AQS獨(dú)占式源碼分析》《J.U.C|AQS共享式源...

    wangdai 評(píng)論0 收藏0
  • Java多線(xiàn)程進(jìn)階(六)—— J.U.C之locks框架:AQS綜述(1)

    摘要:在時(shí),引入了包,該包中的大多數(shù)同步器都是基于來(lái)構(gòu)建的??蚣芴峁┝艘惶淄ㄓ玫臋C(jī)制來(lái)管理同步狀態(tài)阻塞喚醒線(xiàn)程管理等待隊(duì)列。指針用于在結(jié)點(diǎn)線(xiàn)程被取消時(shí),讓當(dāng)前結(jié)點(diǎn)的前驅(qū)直接指向當(dāng)前結(jié)點(diǎn)的后驅(qū)完成出隊(duì)動(dòng)作。 showImg(https://segmentfault.com/img/remote/1460000016012438); 本文首發(fā)于一世流云的專(zhuān)欄:https://segmentfau...

    cocopeak 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<