亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

《java.util.concurrent 包源碼閱讀》16 一種特別的BlockingQueue:SynchronousQueue

2019-11-14 20:59:39
字體:
來源:轉載
供稿:網友
java.util.concurrent 包源碼閱讀》16 一種特別的BlockingQueue:SynchronousQueue

SynchronousQueue是一種很特別的BlockingQueue,任何一個添加元素的操作都必須等到另外一個線程拿走元素才會結束。也就是SynchronousQueue本身不會存儲任何元素,相當于生產者和消費者手遞手直接交易。

SynchronousQueue有一個fair選項,如果fair為true,稱為fair模式,否則就是unfair模式。

在fair模式下,所有等待的生產者線程或者消費者線程會按照開始等待時間依次排隊,然后按照等待先后順序進行匹配交易。這種情況用隊列實現。

在unfair模式下,則剛好相反,后來先匹配,這種情況用棧實現。

     */    public SynchronousQueue(boolean fair) {        transferer = fair ? new TransferQueue() : new TransferStack();    }

因為添加元素和拿走元素是類似手遞手交易的,所以對于拿走元素和添加元素操作,SynchronousQueue調用的是Transferer同一個方法transfer。

當object為null時表示是拿走元素,用于消費者線程,否則則是添加元素,用于生產者線程。因此transfer方法是分析的重點。

abstract Object transfer(Object e, boolean timed, long nanos);

首先來看用于fair模式的TransferQueue的transfer方法:

看代碼之前,來理一下邏輯:

1. 開始隊列肯定是空。

2. 線程進入隊列,如果隊列是空的,那么就添加該線程進入隊列,然后進行等待(要么有匹配線程出現,要么就是該請求超時取消)

3. 第二個線程進入,如果前面一個線程跟它屬于不同類型,也就是說兩者是可以匹配的,那么就從隊列刪除第一個線程。

如果是相同的線程,那么做法參照2。

理清了基本邏輯,也就是會有兩種情況:

1. 隊列為空或者隊列中的等待線程是相同類型

2. 隊列中的等待線程是匹配的類型

        Object transfer(Object e, boolean timed, long nanos) {            QNode s = null;            // e不是null表示是生成者線程,e就是產品,反之就是消費者線程            boolean isData = (e != null);            for (;;) {                QNode t = tail;                QNode h = head;                // tail和head在隊列創建時會被初始化成一個虛擬節點                // 因此發現沒有初始化,重新循環等待直到初始化完成                if (t == null || h == null)                    continue;                // 隊列為空或等待線程類型相同(不同類型才能匹配)                // 這兩種情況都要把當前線程加入到等待隊列中                if (h == t || t.isData == isData) {                    QNode tn = t.next;                    // tail對象已經被更新,出現不一致讀的現象,重新循環                    if (t != tail)                        continue;                    // 添加線程到等待隊列時會先更新當前tail的next,然后                    // 更新tail本身,因此出現只有next被更新的情況,應該                    // 更新tail,然后重新循環                    if (tn != null) {                        advanceTail(t, tn);                        continue;                    }                    // 設定了超時,剩余等待時間耗盡的時候,就無需再等待                    if (timed && nanos <= 0)                        return null;                    // 首次使用s的時候,新建一個節點保存當前線程和數據來初始化s                    if (s == null)                        s = new QNode(e, isData);                    // 嘗試更新tail的next,把新建節點添加到tail的后面,如果失敗了,就重新循環                    if (!t.casNext(null, s))                        continue;                    // 把新建的節點設置為tail                    advanceTail(t, s);                    // 等待匹配線程,成功匹配則返回的匹配的值                    // 否則返回當前節點,因此s和x相同表示請求被取消                    Object x = awaitFulfill(s, e, timed, nanos);                    if (x == s) {                        clean(t, s);                        return null;                    }                    // 這個時候已經匹配成功了,s應該是排在第一個的等待線程                    // 如果s依然在隊列中,那么需要更新head。                    // 更新head的方法是把s這個排在第一位的節點作為新的head                    // 因此需要重置一些屬性使它變成虛擬節點                    if (!s.isOffList()) {                        advanceHead(t, s);                        if (x != null)                            s.item = s;                        s.waiter = null;                    }                    // x不為null表示拿到匹配線程的數據(消費者拿到生產者的數據),                    // 因此返回該數據,否則返回本身的數據(生成者返回自己的數據)                    return (x != null) ? x : e;                } else { // 線程可以匹配                    // 因為是隊列,因此匹配的是第一個節點                    QNode m = h.next;                    // 同樣需要檢查不一致讀的情況                    if (t != tail || m == null || h != head)                        continue;                    Object x = m.item;                    // 匹配失敗時,把m從隊列中移走,重新循環                    if (isData == (x != null) ||    // m已經被匹配了                        x == m ||                   // m已經被取消了                        !m.casItem(x, e)) {         // 用CAS設置m的數據為null                        advanceHead(h, m);                        continue;                    }                    // 匹配成功,更新head                    advanceHead(h, m);                    // 解除m的線程等待狀態                    LockSupport.unpark(m.waiter);                    // 返回匹配的數據                    return (x != null) ? x : e;                }            }        }

接著來用于Unfair模式的TransferStack的transfer方法

大體邏輯應該是一樣的,不同就是隊列的入隊和出隊操作對應到棧時就是入棧和出棧的操作。

        Object transfer(Object e, boolean timed, long nanos) {            SNode s = null;            int mode = (e == null) ? REQUEST : DATA;            for (;;) {                SNode h = head;                // 棧為空或者節點類型相同的情況                if (h == null || h.mode == mode) {                    if (timed && nanos <= 0) {                        // 檢查棧頂節點是否已經取消,如果已經取消,彈出節點                        // 重新循環,接著檢查新的棧頂節點                        if (h != null && h.isCancelled())                            casHead(h, h.next);                        else                            return null;                    // 新建節點,并且嘗試把新節點入棧                    } else if (casHead(h, s = snode(s, e, h, mode))) {                        // 等待匹配,如果發現是被取消的情況,則釋放節點,返回null                        SNode m = awaitFulfill(s, timed, nanos);                        if (m == s) {                            clean(s);                            return null;                        }                        // 如果匹配的成功兩個節點是棧頂的兩個節點                        // 把這兩個節點都彈出                        if ((h = head) != null && h.next == s)                            casHead(h, s.next);     // help s's fulfiller                        return (mode == REQUEST) ? m.item : s.item;                    }                } else if (!isFulfilling(h.mode)) { // 棧頂節點沒有和其他線程在匹配,可以匹配                    if (h.isCancelled())            // 棧頂節點的請求已經被取消                        casHead(h, h.next);         // 移除棧頂元素重新循環                    // 嘗試把該節點也入棧,該節點設置為正在匹配的狀態                    // 也就是isFulfilling返回true                    else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {                        for (;;) {                            // 棧頂節點(當前線程的節點)和它的下一個節點進行匹配,m為null意味著                            // 棧里沒有其他節點了,因為前面該節點入棧了,需要彈出這個節點重新循環                            SNode m = s.next;                            if (m == null) {                                casHead(s, null);                                s = null;                                break;                            }                            // 這個時候是有節點可以匹配的,嘗試為這兩個節點做匹配                            SNode mn = m.next;                            // m和s匹配成功,彈出這兩個節點,返回數據;匹配失敗,把m移除                            if (m.tryMatch(s)) {                                casHead(s, mn);                                return (mode == REQUEST) ? m.item : s.item;                            } else                                s.casNext(m, mn);                        }                    }                // 棧頂正在匹配,參見代碼:                // else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {                // 做法基本類似,只是這里幫助其他線程匹配,無論成功與否                // 都要重新循環                } else {                    SNode m = h.next;                                   if (m == null)                        casHead(h, null);                    else {                        SNode mn = m.next;                        if (m.tryMatch(h))                            casHead(h, mn);                        else                            h.casNext(m, mn);                    }                }            }        }

TransferQueue和TransferStack的算法實現可以參考 這里


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人久久久久爱| 亚洲国产欧美一区二区三区同亚洲| 欧美性猛交xxxx乱大交3| 欧美一性一乱一交一视频| 欧美日韩国产91| 欧美交受高潮1| 亚洲a在线播放| 欧美日本高清一区| 亚洲性69xxxbbb| 欧美性猛交xxxx偷拍洗澡| 一区二区三区亚洲| 欧美一级视频免费在线观看| 亚洲第一级黄色片| 这里只有精品视频在线| 久久人91精品久久久久久不卡| 日本在线观看天堂男亚洲| 91精品国产99久久久久久| 国产一区私人高清影院| 亚洲精品网址在线观看| 国产精品久久网| 成人网址在线观看| 久久久精品影院| 久久久电影免费观看完整版| 久久九九亚洲综合| 91嫩草在线视频| 草民午夜欧美限制a级福利片| 韩国一区二区电影| 久久国产精品亚洲| 国产一区二区三区久久精品| 国产精品亚洲精品| 2019国产精品自在线拍国产不卡| 精品视频www| 欧洲亚洲女同hd| 国语自产精品视频在线看抢先版图片| 欧美日韩免费在线观看| 久久精品久久精品亚洲人| 国产一区二区激情| 欧美国产日韩精品| 欧美性生交xxxxxdddd| 久久久精品一区二区三区| 日韩av在线天堂网| 国产精品劲爆视频| www.亚洲天堂| 亚洲人在线观看| 色无极影院亚洲| 91成人免费观看网站| 国产91成人video| 日韩视频在线免费| 欧美日韩中文字幕在线| 国产精品久久久久久久久久ktv| 91国自产精品中文字幕亚洲| 性色av一区二区三区在线观看| 日韩av在线影视| 黑人巨大精品欧美一区二区一视频| 成人黄色午夜影院| 欧美日韩精品在线观看| 国产美女被下药99| 国产精品久久久久久久久久久久久久| 欧美人在线观看| 国产精品久久久久久久久久新婚| 成人网欧美在线视频| 伊人伊成久久人综合网小说| 亚洲精品白浆高清久久久久久| 亚洲一级免费视频| 久久精品美女视频网站| 欧美黑人性视频| 国产精品视频久久久| 亚洲最大福利视频| 91久久精品日日躁夜夜躁国产| 97国产一区二区精品久久呦| 日本一区二三区好的精华液| 日韩不卡中文字幕| 日韩风俗一区 二区| 日韩欧美在线视频免费观看| 亚洲加勒比久久88色综合| 成人性生交大片免费观看嘿嘿视频| 日韩大陆欧美高清视频区| 欧美精品电影免费在线观看| 欧洲精品在线视频| 成人写真福利网| 国产精品三级美女白浆呻吟| 日本免费在线精品| 国产成人亚洲综合青青| 亚洲图片欧美午夜| 国产深夜精品福利| 久久精品国产2020观看福利| 久久久精品中文字幕| 国产一区二区三区在线观看网站| 亚洲精品免费一区二区三区| 精品国产户外野外| www.欧美视频| 欧美电影在线观看| www.亚洲人.com| 久久久久久中文字幕| 91美女片黄在线观| 国产精自产拍久久久久久| 国产精品一区二区女厕厕| 国产一区私人高清影院| 精品福利视频导航| 久久免费视频网站| 亚洲男人天堂手机在线| 欧美中文字幕在线| 亚洲精品午夜精品| 欧美激情亚洲精品| 欧美丝袜美女中出在线| 日韩欧中文字幕| 九色精品免费永久在线| 国产精品丝袜高跟| 国产伦精品免费视频| 欧美中在线观看| 欧美日韩亚洲一区二| 国产精品亚洲аv天堂网| 57pao国产成人免费| 国产精品久久久久7777婷婷| 精品亚洲一区二区三区四区五区| 国产精品久久久久福利| 亚洲人永久免费| 日韩精品在线免费观看| 久久久久久国产精品| 久久久久九九九九| 亚洲成人中文字幕| 国产精品伦子伦免费视频| 国产91在线高潮白浆在线观看| 97国产在线观看| 亚洲欧美日韩在线高清直播| 另类少妇人与禽zozz0性伦| 欧美精品在线观看91| 欧美日韩性视频在线| 久久精品91久久久久久再现| 国产亚洲精品日韩| 日韩专区中文字幕| 成人在线中文字幕| 久久综合色88| 久久色免费在线视频| 亚洲国产精品一区二区久| 国产成人jvid在线播放| 久久精品在线播放| 国产一区二区在线免费视频| 亚洲欧美日韩精品久久| 91精品国产乱码久久久久久久久| 国产精品亚洲片夜色在线| 欧美另类暴力丝袜| 精品国产精品三级精品av网址| 欧美性猛交xxxx富婆| 久久精彩免费视频| 国产欧美va欧美va香蕉在线| 成人女保姆的销魂服务| 日韩精品欧美国产精品忘忧草| 久久久久久久网站| 91高清视频免费| 国语自产精品视频在线看一大j8| 色婷婷综合久久久久中文字幕1| 亚洲欧美日韩一区二区三区在线| 国产精品久久久| 国产精品视频一区国模私拍| 久久亚洲精品毛片| 午夜欧美大片免费观看| 欧美视频在线免费| 精品人伦一区二区三区蜜桃免费| 亚洲欧美国产另类| 久久99亚洲热视| 国产成人一区三区| 91久久久久久| 91久久在线观看|