麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

《java.util.concurrent 包源碼閱讀》18 Exchanger

2019-11-14 21:00:58
字體:
供稿:網(wǎng)友
java.util.concurrent 包源碼閱讀》18 Exchanger

Exchanger可以看做雙向數(shù)據(jù)傳輸?shù)腟ynchronousQueue,即沒有生產(chǎn)者和消費(fèi)者之分,任意兩個線程都可以交換數(shù)據(jù)。

在JDK5中Exchanger被設(shè)計成一個容量為1的容器,存放一個等待線程,直到有另外線程到來就會發(fā)生數(shù)據(jù)交換,然后清空容器,等到下一個到來的線程。

從JDK6開始,Exchanger用了類似ConcurrentMap的分段思想,提供了多個slot,增加了并發(fā)執(zhí)行時的吞吐量。

Exchanger不存在公平不公平的模式,因為沒有排隊的情況發(fā)生,只要有兩個線程就可以發(fā)生數(shù)據(jù)交換。

直接看核心方法:

    PRivate Object doExchange(Object item, boolean timed, long nanos) {        Node me = new Node(item);        // index是線程ID的hash值映射到0到max之間的一個值        // 一般情況下max為0,這樣線程交換數(shù)據(jù)只會使用第一個slot,        // 即index是0,而max不為0情況請看下面的循環(huán)        int index = hashIndex();        // CAS操作失敗的次數(shù)        int fails = 0;        for (;;) {            // 當(dāng)前slot中存儲的對象,也就是Node            Object y;            Slot slot = arena[index];            // 延遲加載,即只有當(dāng)slot為null時才創(chuàng)建一個slot            // 延遲加載后重新循環(huán)一次            if (slot == null)                createSlot(index);            // slot中有數(shù)據(jù),也就意味著有線程在等待交換數(shù)據(jù)            // 這時可以嘗試用CAS重置slot(把slot存儲的對象設(shè)為null)            // 用slot中存儲的對象和當(dāng)前線程進(jìn)行數(shù)據(jù)交換            // 如果交換成功就通知原先等待的線程            else if ((y = slot.get()) != null &&                     slot.compareAndSet(y, null)) {                Node you = (Node)y;                if (you.compareAndSet(null, item)) {                    LockSupport.unpark(you.waiter);                    return you.item;                }                // 如果slot存儲的對象已經(jīng)被重置為null,但是數(shù)據(jù)交換失敗了                // 這時就意味著這個等待的線程的交換請求被取消了                // 在分析wait類型的方法代碼時會看到如何處理這種情況            }            // 如果slot中沒有存儲對象,那么首先嘗試把當(dāng)前線程存儲到slot中            // 如果存儲失敗了,就重新循環(huán)            else if (y == null &&                     slot.compareAndSet(null, me)) {                // index為0意味著僅僅有當(dāng)前線程在等待交換數(shù)據(jù),因此直接等待即可                if (index == 0)                    return timed ?                        awaitNanos(me, slot, nanos) :                        await(me, slot);                // 所謂的spin wait:就是固定次數(shù)循環(huán),每次計數(shù)減一                // 對于單核系統(tǒng)來說,spin wait是不做的,因為單核                // 做wait時需要占用CPU,其他線程是無法使用CPU,因此這樣                // 的等待毫無意義。而多核系統(tǒng)中spin值為2000,也就是會做                // 2000次循環(huán)。                // 如果循環(huán)完成后依然沒有得到交換的數(shù)據(jù),那么會返回一個                // CANCEL對象表示請求依舊被取消,并且把Node從slot中清除                Object v = spinWait(me, slot);                if (v != CANCEL)                    return v;                // 如果取消了,就新建一個Node取消原先取消的Node用于下次循環(huán)                me = new Node(item);                int m = max.get();                // index除2,縮小slot的范圍                // 同時如果m過大,減小m                if (m > (index >>>= 1))                    max.compareAndSet(m, m - 1);            }            // 允許CAS失敗兩次,因為兩個else if中都有CAS,因此這里            // 允許兩個else if的CAS操作都失敗過            else if (++fails > 1) {                int m = max.get();                // 失敗超過3次,增大m,并且從m處重新索引                if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1))                    index = m + 1;                // 當(dāng)index小于0,回到m,重新循環(huán)                else if (--index < 0)                    index = m;            }        }    }

這篇文章關(guān)于索引index這塊弄得不是很清楚,后續(xù)會繼續(xù)研究,及時更新。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 曰韩一级片 | 毛片在线视频观看 | 欧美日韩在线中文字幕 | 深夜精品福利 | 成人不卡在线观看 | 欧美日韩手机在线观看 | 久久久久久久99 | 国产精品av久久久久久无 | 一区二区免费看 | av在线1| 成人在线免费小视频 | 欧美性生交xxxxx久久久缅北 | 一级裸体视频 | 黄色免费av | 精品国产乱码久久久久久丨区2区 | 国产性tv国产精品 | 欧美一级淫片a免费播放口 91九色蝌蚪国产 | h色网站免费观看 | 精品国内视频 | 成年人黄色片视频 | 9999精品 | 98国内自拍在线视频 | 在线 日本 制服 中文 欧美 | lutube成人福利在线观看污 | 女人叉开腿让男人桶 | 国产亚洲精品综合一区91555 | 午夜噜噜噜 | 欧美特级黄色 | 国产亚洲精久久久久久蜜臀 | 亚洲一区二区三区四区精品 | a一级黄色大片 | 国产免费资源 | 久久精品一二三区 | 国产午夜电影 | 色的综合| 欧美性受ⅹ╳╳╳黑人a性爽 | www69xxxxx| 精品一区二区久久久久久久网精 | av不卡免费在线观看 | 久久精品一级 | 欧洲黄色一级视频 |