日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Java并發(fā)編程之CountDownLatch源碼解析

瀏覽:215日期:2022-08-14 09:54:38
一、前言

CountDownLatch維護(hù)了一個計數(shù)器(還是是state字段),調(diào)用countDown方法會將計數(shù)器減1,調(diào)用await方法會阻塞線程直到計數(shù)器變?yōu)?。可以用于實現(xiàn)一個線程等待所有子線程任務(wù)完成之后再繼續(xù)執(zhí)行的邏輯,也可以實現(xiàn)類似簡易CyclicBarrier的功能,達(dá)到讓多個線程等待同時開始執(zhí)行某一段邏輯目的。

二、使用 一個線程等待其它線程執(zhí)行完再繼續(xù)執(zhí)行

......CountDownLatch cdl = new CountDownLatch(10);ExecutorService es = Executors.newFixedThreadPool(10);for (int i = 0; i < 10; i++) {es.execute(() -> {//do somethingcdl.countDown();});}cdl.await();...... 實現(xiàn)類似CyclicBarrier的功能,先await,再countDown

......CountDownLatch cdl = new CountDownLatch(1);ExecutorService es = Executors.newFixedThreadPool(10);for (int i = 0; i < 10; i++) { es.execute(() -> {cdl.await();//do something });}Thread.sleep(10000L);cdl.countDown();......三、源碼分析

CountDownLatch的結(jié)構(gòu)和ReentrantLock、Semaphore的結(jié)構(gòu)類似,也是使用的內(nèi)部類Sync繼承AQS的方式,并且重寫了tryAcquireShared和tryReleaseShared方法。

還是首先來看構(gòu)造函數(shù):

public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException('count < 0');this.sync = new Sync(count); }

需要傳入一個大于0的count,代表CountDownLatch計數(shù)器的初始值,通過Sync的構(gòu)造函數(shù)最終賦值給父類AQS的state字段。可一個看到這個state字段用法多多,在ReentrantLock中使用0和1來標(biāo)識鎖的狀態(tài),Semaphore中用來標(biāo)識信號量,此處又用來表示計數(shù)器。

CountDownLatch要通過await方法完成阻塞,先來看看這個方法是如何實現(xiàn)的:

public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1); }

調(diào)用的是sync的acquireSharedInterruptibly方法,該方法定義在AQS中,Semaphore也調(diào)用的這個方法:

public final void acquireSharedInterruptibly(int arg) throws InterruptedException {if (Thread.interrupted()) throw new InterruptedException();if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); }

這個方法的邏輯前面在解析SemaPhore的時候細(xì)說過了,這里不再贅述,主要就是兩個方法的調(diào)用,先通過tryAcquireShared方法嘗試獲取'許可',返回值代表此次獲取后的剩余量,如果大于等于0表示獲取成功,否則表示失敗。如果失敗,那么就會進(jìn)入doAcquireSharedInterruptibly方法執(zhí)行入隊阻塞的邏輯。這里我們主要到CountDownLatch中看看tryAcquireShared方法的實現(xiàn):

protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1;}

和Semaphore的實現(xiàn)中每次將state減去requires不同,這里直接判斷state是否為0,如果為0那么返回1,表示獲取'許可'成功;如果不為0,表示失敗,則需要入隊阻塞。從這個tryAcquireShared方法就能看出CountDownLatch的邏輯了:等到state變?yōu)榱?,那么所有線程都能獲取運行許可。

那么我們接下來來到countDown方法:

public void countDown() {sync.releaseShared(1); }

調(diào)用的是sync的releaseShared方法,該方法定義在父類AQS中,Semaphore使用的也是這個方法:

public final boolean releaseShared(int arg) {if (tryReleaseShared(arg)) {//當(dāng)state從非 doReleaseShared(); return true;}return false; }

前面提到了CountDownLatch也重寫了tryReleaseShared方法:

protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) {int c = getState();if (c == 0)//如果state等于0了直接返回false//保證在并發(fā)情況下,最多只會有一個線程返回true//也包括調(diào)用countDown的次數(shù)超過state的初始值 return false;int nextc = c-1;if (compareAndSetState(c, nextc))//如果返回true,表示state從非0變?yōu)榱?//那么后續(xù)需要喚醒阻塞線程 return nextc == 0; }}

Semaphore在釋放信號量的時候,是將獲取的許可歸還到state中,但是CountDownLatch沒有獲取許可的邏輯(獲取許可的時候是判斷state是否等于0),所以在countDown的時候沒有釋放的邏輯,就是將state減1,然后根據(jù)state減1之后的值是否為0判斷release是否成功,如果state本來大于0,經(jīng)過減1之后變?yōu)榱?,那么返回true。tryReleaseShared方法的返回值決定了后續(xù)需不需要調(diào)用doReleaseShared方法喚醒阻塞線程。

這里有個邏輯:如果state已經(jīng)為0,那么返回false。這個主要應(yīng)對兩種情況:

調(diào)用countDown的次數(shù)超過了state的初始值多 線程并發(fā)調(diào)用的時候保證只有一個線程去完成阻塞線程的喚醒操作

可以看到CountDownLatch沒有鎖的概念,countDown方法可以被一個線程重復(fù)調(diào)用,只需要對state做reduce操作,而不用關(guān)心是誰做的reduce。如果tryReleaseShared返回true,那么表示需要在后面進(jìn)入doReleaseShared方法,該方法和Semaphore中調(diào)用的方法是同一個,主要是喚醒阻塞線程或者設(shè)置PROPAGAGE狀態(tài),這里也不再贅述~

阻塞線程被喚醒之后,會在doAcquireSharedInterruptibly方法中繼續(xù)循環(huán),雖然和Semaphore調(diào)用的是同樣的方法,但是這里有不一樣的地方,所以還是提一句。我們首先回到doAcquireSharedInterruptibly方法:

private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.SHARED);boolean failed = true;try { for (;;) {final Node p = node.predecessor();if (p == head) {//如果head.next被unpark喚醒,說明此時state==0//那么tryAcquireShared會返回1 int r = tryAcquireShared(arg); //r==1 if (r >= 0) { //node節(jié)點被喚醒后,還會繼續(xù)喚醒node.next //這樣依次傳遞,因為在這里的r一定為1setHeadAndPropagate(node, r);p.next = null; // help GCfailed = false;return; }}if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); }} finally { if (failed)cancelAcquire(node);} }

當(dāng)head.next線程被unpark喚醒后,會進(jìn)入tryAcquireShared方法判斷,由于此時state已經(jīng)為0(只有當(dāng)state變?yōu)?時,才會unpark喚醒線程),而前面提到了在CountDownLatch重寫的tryAcquireShared中,如果state==0,那么會返回1,所以會進(jìn)入setHeadAndPropagate方法:

private void setHeadAndPropagate(Node node, int propagate) {Node h = head; // Record old head for check belowsetHead(node);if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) { Node s = node.next; if (s == null || s.isShared())doReleaseShared();} }

該方法在Semaphore中詳細(xì)介紹過,這里我們就站在CountDownLatch的角度來看看。其實很簡單了,注意此時該方法的propagate參數(shù)值是1,那么就會進(jìn)入到下面的if邏輯里,繼續(xù)喚醒下一個node。當(dāng)下一個node對應(yīng)的線程被喚醒后,同樣會進(jìn)入setHeadAndPropagate方法,propagage同樣為1,那么繼續(xù)喚醒下一個node,就這樣依次將整個CLH隊列的節(jié)點都喚醒。

四、總結(jié)

如果單獨把CountDownLatch拿出來看其實是很復(fù)雜的,只是CountDownLatch(包括Semaphore和ReentrantLock)都高度共用了AQS提供的一些方法,而這些方法在前面介紹Semaphore和ReentrantLock的時候已經(jīng)詳細(xì)分析過,所以到本文分析CountDownLatch的時候,只需要關(guān)注它內(nèi)部類Sync重寫的兩個方法:tryAcquireShared和tryReleaseShared,也就是'獲取許可'和'釋放許可'的邏輯。

CountDownLatch在await的邏輯里,如果當(dāng)前state的值大于0,那么會進(jìn)入CLH隊列進(jìn)行阻塞等待unpark喚醒(或者中斷喚醒);在countDown的邏輯里,就是簡單的將state-1,如果一個線程把state從1減為0,那么該線程就會負(fù)責(zé)喚醒head.next節(jié)點,head.next節(jié)點被喚醒后,又會在setHeadAndPropagate方法中喚醒next.next節(jié)點,這樣依次喚醒所有CLH隊列中的阻塞節(jié)點。當(dāng)然,如果線程被中斷喚醒,那么也會進(jìn)入cancelAcquire中進(jìn)行無效節(jié)點的移除邏輯。

到此這篇關(guān)于Java并發(fā)編程之CountDownLatch源碼解析的文章就介紹到這了,更多相關(guān)Java中CountDownLatch源碼解析內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品一区二区99| 日韩欧美综合| 免费美女久久99| 国产视频一区在线观看一区免费| 999久久久亚洲| 激情六月综合| 在线一区免费观看| 亚洲日本在线观看视频| 日本一区中文字幕| 国产精品久久久网站| 欧美a在线观看| 国内揄拍国内精品久久| 中文字幕在线官网| 999国产精品| 六月丁香综合| 视频在线观看一区| 亚洲欧美网站在线观看| 日韩av成人高清| 美腿丝袜亚洲三区| 亚洲午夜天堂| 午夜久久免费观看| 亚洲精品影视| 欧美极品一区二区三区| 首页国产精品| 亚洲一级网站| 中文字幕视频精品一区二区三区 | 狠狠久久伊人| 成人精品天堂一区二区三区| 久久精品播放| 六月婷婷一区| 国产激情精品一区二区三区| 日韩电影免费在线观看| 女人天堂亚洲aⅴ在线观看| 亚洲一区av| 国产精品亚洲欧美日韩一区在线 | 日韩网站在线| 日韩精品电影一区亚洲| 美女视频免费精品| 日韩精品不卡一区二区| 蜜臀av免费一区二区三区| 亚洲精品女人| 老司机免费视频一区二区三区| 日韩精品专区| 亚洲精品激情| 97精品中文字幕| 久热re这里精品视频在线6| 久久久人人人| 欧美一区影院| 亚洲一级大片| 视频一区日韩| 国产美女视频一区二区| 国产欧美日韩视频在线| 国产精品片aa在线观看| 国产日韩在线观看视频| 国产一区2区在线观看| 宅男在线一区| 国产精品美女久久久久久不卡| 久久国产中文字幕| 国产欧美另类| 99视频精品免费观看| 久久精品一区二区国产| 91成人精品视频| 国产精品扒开腿做爽爽爽软件| 蜜臀av免费一区二区三区| 国产精品一区二区精品视频观看| 婷婷综合五月| 精品视频自拍| 综合激情网站| 福利视频一区| 免费成人在线影院| 91视频一区| 日韩激情中文字幕| 国产+成+人+亚洲欧洲在线| 日av在线不卡| 欧美不卡高清一区二区三区| 亚洲专区视频| 91精品精品| 欧美国产极品| 日韩区欧美区| 日韩亚洲精品在线| 日韩一区二区三区免费播放| 日本视频一区二区| 日韩网站在线| 日韩精品午夜| 国产欧美高清视频在线| 美女久久一区| 久久精品99久久无色码中文字幕| 国产精品videosex极品| 在线精品国产亚洲| 国产亚洲一级| 日韩不卡在线| 成人精品国产亚洲| 国产三级精品三级在线观看国产| 欧美午夜不卡| 日韩欧美综合| 精品五月天堂| 国产美女精品视频免费播放软件| 亚洲一区二区三区免费在线观看| 三级在线看中文字幕完整版| 日韩精彩视频在线观看| 视频一区二区三区中文字幕| 91精品国产91久久久久久黑人| 韩国女主播一区二区三区| 欧美伊人久久| 日本a口亚洲| 综合激情在线| 亚洲专区视频| 亚洲伊人精品酒店| 视频在线观看国产精品| 91精品一区二区三区综合| 热三久草你在线| 精品免费视频| 精品精品国产三级a∨在线| 日韩精品欧美精品| 亚洲激情另类| 夜夜嗨网站十八久久| 2023国产精品久久久精品双| 色婷婷久久久| 欧美男人天堂| 成人自拍av| 九色porny丨国产首页在线| 日本精品黄色| 福利在线免费视频| 麻豆mv在线观看| 麻豆成全视频免费观看在线看| 国产videos久久| 正在播放日韩精品| 久久精品动漫| 亚洲作爱视频| 亚洲综合欧美| 日本亚洲最大的色成网站www| 日韩中文字幕在线一区| 日本特黄久久久高潮| 欧美一区久久| 麻豆精品视频在线| 成人国产精品一区二区免费麻豆| 日韩在线不卡| 五月精品视频| 天堂俺去俺来也www久久婷婷| 91精品一区| 久久亚洲人体| 在线观看精品| 久久夜色精品| 欧美一区在线观看视频| 国产欧美高清| 中文字幕人成乱码在线观看 | 亚洲综合日韩| 日韩高清在线一区| 欧美黄色精品| 亚洲不卡系列| 欧美中文字幕| 国产亚洲久久| 国产理论在线| 夜夜嗨一区二区| 日本少妇一区二区| 国内在线观看一区二区三区| аⅴ资源天堂资源库在线| 亚洲福利免费| 午夜久久av| 国产精品国产一区| 狠狠色综合网| 国产欧美88| 999久久久国产精品| 亚洲97av| 国产一二在线播放| 亚洲尤物在线| 国产精品久久乐| 免费久久精品| 欧美一区精品| 99精品综合| 日本成人一区二区| 精品国产不卡一区二区| 欧美搞黄网站| 国产日韩视频在线| 午夜精品成人av| 日韩二区三区在线观看| 激情不卡一区二区三区视频在线| 免费黄色成人| 国产精品一区二区三区四区在线观看| 欧美日韩视频网站| 日韩精品五月天| 偷拍精品精品一区二区三区| 日本一区二区三区中文字幕| 日韩在线综合| 日韩欧美精品一区二区综合视频| 国产一二在线播放| 鲁大师成人一区二区三区| 国产高清日韩| 国产精品免费看| 国产一区调教| 日韩激情一区二区| 国产综合婷婷| 久久av网址| 丝袜美腿成人在线| 国产一区二区三区视频在线| 亚洲影院天堂中文av色| 久久久久.com| 久久不卡国产精品一区二区| 免费国产自线拍一欧美视频| 国产一区二区三区日韩精品|