CyclicBarrier原始碼解析

2021-10-06 15:40:09 字數 3102 閱讀 2913

乙個多執行緒協同器,它可以讓一組執行緒相互等待,當等待的數量達到預設數量時這組執行緒通過等待繼續工作。說得形象點,cyclicbarrier就好比汽車站滾動發車的模式,把客車看著cyclicbarrier,乘客看著是各個任務執行緒,當乘客到達客車時,需要等待另外的乘客,當乘客到齊後自動發車,如果等待乘客超時了,則將乘客全部趕下車(司機太**了),然後重新安排依次上車(是否要上車由乘客自己決定);每個上車的乘客都需要判斷自己是否是這輛車的最後乙個乘客,如果不是,則上車後立即開始睡覺,如果是最後乙個,則他需要叫醒所有乘客。當然客車站在建立這些客車的時候可能會做一些額外的事情,例如所有乘客到齊後,司機給大夥一人發一瓶礦泉水,或者是其它的,但是前提條件就是乘客到齊。

圖中的cyclicbarrier需要等待8個執行緒到達後才會「發車」,目前已經到達的執行緒有4個,還需要等待4個執行緒;執行緒上車的過程(也就是進入await的過程)是要進行排隊的,這裡是通過reentrantlock來實現的,上車後的睡眠是通過鎖的條件等待condition來實現的。

public

class

cyclicbarrier

//執行緒進入條件等待時需要獲取鎖

private

final reentrantlock lock =

newreentrantlock()

;//等待條件

private

final condition trip = lock.

newcondition()

;//每次需要協同的執行緒數(客車的準載數)

private

final

int parties;

//這組執行緒(parties)滿足協同條件後需要做的一件事情

private

final runnable barriercommand;

//標識例項,乙個generation代表一次執行緒協同

private generation generation =

newgeneration()

;//還需要等待的執行緒數量(還未上車的乘客數)

private

int count;

//最後乙個乘客上車後使用的工具,喚醒所有乘客,

private

void

nextgeneration()

//等待超時後,司機生氣了,就用這個方法把大家叫醒,然後把這輛車標記為broken,把所有人趕下車

private

void

breakbarrier()

//車輛的構造器,客車佔為車輛設定的規則

public

cyclicbarrier

(int parties, runnable barrieraction)

//同上,只是執行緒協同完成後不需要做額外的動作

public

cyclicbarrier

(int parties)

/** 一些核心方法

**/}

cyclicbarrier的核心方法是await,該方法是執行緒相互等待的關鍵,它有兩種實現,一種是帶等待超時的,一種是不會等待超時:

public

intawait()

throws interruptedexception, brokenbarrierexception

catch

(timeoutexception toe)

}public

intawait

(long timeout, timeunit unit)

throws interruptedexception, brokenbarrierexception,timeoutexception

從**可以看出,其核心都是使用了dowait這個方法

private

intdowait

(boolean timed,

long nanos)

throws interruptedexception, brokenbarrierexception,

timeoutexception

int index =

--count;

//上車成功,還需要上車的人數減1

if(index ==0)

finally

}//如果上車的不是最後乙個乘客

for(;;

)catch

(interruptedexception ie)

else}if

(g.broken)

throw

newbrokenbarrierexception()

;//被標記為了broken(這可能自己前面標的,也可能其它執行緒標的),則所有的執行緒都丟擲異常。

if(g != generation)

//如果是正常被喚醒,則直接返回還需上車的人(理論上應該是0)

return index;

if(timed && nanos <=

0l)}

}finally

}

從**可以看出,cyclicbarrier的實現是利用條件等待,用到條件等待當然就會用到鎖。

多個執行緒協調過程中,只要有乙個執行緒被中斷或者發生異常,則整個協調取消。

相同點:

1.都能讓多個執行緒協調,在某乙個點上等待

不同點:

1.cyclicbarrier是多個執行緒自行協同,當執行緒到達等待數量時自動放行,而countdownlatch是多個執行緒阻塞後,需要外界條件達到某種狀態的時候才會被統一喚醒,即cyclicbarrier只需要各個執行緒await,而countdownlatch還需要額外是countdown。

2.實現上,cyclicbarrier是使用獨佔鎖+condition實現的,而countdownlatch是自己實現aqs,利用共享鎖的原理實現。

3.countdownlatch一旦滿足條件後需要重新初始化才能再使用,而cyclicbarrier可以迴圈使用。

併發程式設計之 CyclicBarrier 原始碼分析

在之前的介紹 countdownlatch 的文章中,countdown 可以實現多個執行緒協調,在所有指定執行緒完成後,主線程才執行任務。但是,countdownlatch 有個缺陷,這點 jdk 的文件中也說了 他只能使用一次。在有些場合,似乎有些浪費,需要不停的建立 countdownlatc...

AbstractCollection原始碼分析

abstractcollection抽象類提供了collection的骨架實現,collection分析請看 這裡直接看它的 是如何實現的.public abstract iterator iterator 該方法沒有實現.public abstract int size 該方法沒有實現.publi...

ThreadPoolExecutor原始碼閱讀

執行緒池解決兩個問題 一是復用執行緒,減少建立銷毀執行緒帶來系統開銷 二是限定系統資源使用邊界,避免大量執行緒消耗盡系統記憶體 適用於互不依賴,執行時間短,不需要對執行緒控制操作的執行緒 新增任務時,1.若執行緒數量小於corepoolsize,則新增執行緒執行任務 2.若執行緒數量大於等於core...