CyclicBarrier線程同步共享變量底層原理示例解析
引言
CyclicBarrier是Java.util.concurrent包中提供的另一個(gè)同步工具類,它允許一組線程在某個(gè)共同點(diǎn)處相互等待,并在所有線程都達(dá)到某個(gè)條件時(shí)繼續(xù)執(zhí)行。
CyclicBarrier的代碼示例
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierExample { public static void main(String[] args) { int workerCount = 3; Runnable barrierAction = () -> System.out.println("All workers have reached the barrier."); CyclicBarrier cyclicBarrier = new CyclicBarrier(workerCount, barrierAction); for (int i = 0; i < workerCount; i++) { Thread worker = new Thread(new Worker(cyclicBarrier)); worker.start(); } } static class Worker implements Runnable { private final CyclicBarrier cyclicBarrier; public Worker(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { try { // 模擬工作任務(wù)的執(zhí)行 Thread.sleep(2000); System.out.println("Worker " + Thread.currentThread().getId() + " has reached the barrier."); cyclicBarrier.await(); // 工作線程到達(dá)屏障,等待其他線程 System.out.println("Worker " + Thread.currentThread().getId() + " continues its work."); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } } } }
打印結(jié)果:
Worker 13 has reached the barrier.
Worker 14 has reached the barrier.
Worker 12 has reached the barrier.
All workers have reached the barrier.
Worker 14 continues its work.
Worker 13 continues its work.
Worker 12 continues its work.
首先,創(chuàng)建了一個(gè)CyclicBarrier對(duì)象cyclicBarrier,并指定workerCount為3(代表需要等待的線程數(shù)),并設(shè)置barrierAction為一個(gè)Runnable,用于在所有線程到達(dá)屏障時(shí)執(zhí)行。
然后,使用一個(gè)for循環(huán)創(chuàng)建了3個(gè)工作線程(Worker),每個(gè)工作線程在完成一部分任務(wù)后都會(huì)調(diào)用await()方法來等待其他線程。在工作線程內(nèi)部,它們會(huì)先模擬一段工作任務(wù)的執(zhí)行,然后調(diào)用cyclicBarrier.await()方法等待其他線程。
當(dāng)所有的工作線程都到達(dá)屏障時(shí),即達(dá)到指定的workerCount時(shí),它們就會(huì)繼續(xù)執(zhí)行后續(xù)的任務(wù)。CyclicBarrier會(huì)自動(dòng)重置計(jì)數(shù)器,可以繼續(xù)使用。
在示例中,為了模擬工作任務(wù)的執(zhí)行,工作線程通過Thread.sleep(2000)來暫停2秒鐘。然后,每個(gè)工作線程輸出自己到達(dá)屏障的信息,等待其他線程。當(dāng)所有線程都到達(dá)屏障時(shí),會(huì)執(zhí)行設(shè)置的barrierAction,即輸出所有工作線程都到達(dá)了屏障。在此之后,工作線程會(huì)繼續(xù)執(zhí)行后續(xù)的工作任務(wù)。
小結(jié):
CyclicBarrier可以用于在多個(gè)線程中實(shí)現(xiàn)同步,當(dāng)所有線程都到達(dá)屏障時(shí),才能繼續(xù)執(zhí)行后續(xù)的任務(wù)。它常用于需要等待所有線程完成一定階段的任務(wù)后再進(jìn)行下一階段的場(chǎng)景。
使用CyclicBarrier示例 模擬收集龍珠的場(chǎng)景
當(dāng)收集到7顆龍珠后,會(huì)觸發(fā)一個(gè)動(dòng)作(召喚神龍)。
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierDemo { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> { System.out.println("召喚神龍"); }); for (int i = 1; i <= 7; i++) { final int temp = i; new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t 收集到第" + temp + "顆龍珠"); try { cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } }, String.valueOf(i)).start(); } } }
在這個(gè)示例中,我們創(chuàng)建了一個(gè) CyclicBarrier
對(duì)象,指定計(jì)數(shù)器的值為 7,當(dāng) 7 個(gè)線程都調(diào)用了 await()
方法后,會(huì)觸發(fā)傳入的 Runnable
對(duì)象,即召喚神龍的動(dòng)作。
在 for
循環(huán)中,我們創(chuàng)建了 7 個(gè)線程,并分別模擬收集到不同的龍珠。每個(gè)線程執(zhí)行完收集龍珠的操作后,調(diào)用 cyclicBarrier.await()
方法,等待其他線程。
當(dāng)所有線程都調(diào)用了 await()
方法后,CyclicBarrier 中的計(jì)數(shù)器會(huì)達(dá)到設(shè)定的值,觸發(fā)召喚神龍的動(dòng)作。輸出結(jié)果可能類似于以下內(nèi)容:
1 收集到第1顆龍珠
2 收集到第2顆龍珠
3 收集到第3顆龍珠
4 收集到第4顆龍珠
5 收集到第5顆龍珠
6 收集到第6顆龍珠
7 收集到第7顆龍珠
召喚神龍
這個(gè)示例展示了如何使用 CyclicBarrier 來等待多個(gè)工作線程執(zhí)行完畢,并在所有線程完成后觸發(fā)一個(gè)動(dòng)作。
CyclicBarrier 底層原理
CyclicBarrier 的底層原理涉及到線程同步和共享變量的操作。
CyclicBarrier 的底層原理是基于 AQS(AbstractQueuedSynchronizer)實(shí)現(xiàn)的。 CyclicBarrier 內(nèi)部維護(hù)了一個(gè)共享的同步狀態(tài)(state)和一個(gè)等待隊(duì)列。每個(gè)線程在調(diào)用 await()
方法時(shí),會(huì)將線程加入等待隊(duì)列,并檢查當(dāng)前狀態(tài)是否為初始狀態(tài)。如果是初始狀態(tài),則線程會(huì)進(jìn)入休眠狀態(tài),等待其他線程的到達(dá)。當(dāng)所有線程都調(diào)用 await()
方法后,它們會(huì)相互喚醒,繼續(xù)執(zhí)行后續(xù)的任務(wù)。同時(shí),CyclicBarrier 的狀態(tài)會(huì)被重置為初始狀態(tài),可以繼續(xù)使用。這樣就實(shí)現(xiàn)了線程之間的協(xié)調(diào)與等待的功能。
在 CyclicBarrier 中,有一個(gè)計(jì)數(shù)器(count)和一個(gè)屏障點(diǎn)(barrier)用于實(shí)現(xiàn)線程的同步。計(jì)數(shù)器的初始值由構(gòu)造函數(shù)傳入,每當(dāng)一個(gè)線程調(diào)用 await()
方法時(shí),計(jì)數(shù)器的值會(huì)減一。當(dāng)計(jì)數(shù)器的值變?yōu)榱銜r(shí),表示所有線程都已到達(dá)屏障點(diǎn),可以繼續(xù)執(zhí)行后續(xù)操作。
CyclicBarrier 使用了共享變量和內(nèi)置的線程同步機(jī)制來實(shí)現(xiàn)等待和通知的功能。具體來說,它使用了以下幾個(gè)關(guān)鍵的方法和數(shù)據(jù)結(jié)構(gòu):
await()
:線程調(diào)用await()
方法時(shí),會(huì)嘗試獲取內(nèi)置的鎖,然后將計(jì)數(shù)器的值減一。如果計(jì)數(shù)器的值不為零,那么線程會(huì)被阻塞,等待其他線程到達(dá)屏障。如果計(jì)數(shù)器的值變?yōu)榱?,那么所有在屏障上等待的線程將會(huì)被喚醒,可以繼續(xù)執(zhí)行后續(xù)操作。- 內(nèi)置的同步機(jī)制:CyclicBarrier 內(nèi)部使用了內(nèi)置的同步機(jī)制,如鎖、條件變量等,來實(shí)現(xiàn)線程的等待和通知機(jī)制。
- 循環(huán)使用的特性:與 CountDownLatch 不同,CyclicBarrier 是可以循環(huán)使用的。當(dāng)所有線程都到達(dá)屏障后,計(jì)數(shù)器會(huì)被重置為初始值,可以進(jìn)行下一輪的等待和通知。
在底層實(shí)現(xiàn)中,CyclicBarrier 使用了類似于 ReentrantLock 和 Condition 的機(jī)制來實(shí)現(xiàn)線程的等待和喚醒。當(dāng)一個(gè)線程調(diào)用 await()
方法時(shí),它會(huì)嘗試獲取內(nèi)置的鎖,然后檢查計(jì)數(shù)器的值。如果計(jì)數(shù)器的值不為零,線程會(huì)通過條件變量進(jìn)入等待狀態(tài)。當(dāng)計(jì)數(shù)器的值變?yōu)榱銜r(shí),最后一個(gè)到達(dá)屏障的線程會(huì)通過條件變量喚醒其他等待的線程,使它們繼續(xù)執(zhí)行。
需要注意的是,CyclicBarrier 是可重入的,即同一個(gè)線程可以多次調(diào)用 await()
方法等待其他線程到達(dá)屏障。只有當(dāng)所有線程都調(diào)用了 await()
方法,計(jì)數(shù)器的值才會(huì)變?yōu)榱?,觸發(fā)屏障的打開。
總結(jié)
CyclicBarrier 的底層原理是通過共享變量和內(nèi)置的線程同步機(jī)制來實(shí)現(xiàn)線程的等待和通知。它提供了一種循環(huán)使用的屏障機(jī)制,可以在某個(gè)屏障點(diǎn)上同步等待,然后同時(shí)繼續(xù)執(zhí)行后續(xù)的任務(wù)。
以上就是CyclicBarrier線程同步共享變量底層原理示例解析的詳細(xì)內(nèi)容,更多關(guān)于CyclicBarrier線程同步共享變量的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot多環(huán)境開發(fā)與日志小結(jié)
這篇文章主要介紹了SpringBoot多環(huán)境開發(fā)與日志,下面給大家說一下如何基于多環(huán)境開發(fā)做配置獨(dú)立管理,務(wù)必掌握,需要的朋友可以參考下2022-08-08Java數(shù)據(jù)脫敏實(shí)現(xiàn)的方法總結(jié)
數(shù)據(jù)脫敏,指的是對(duì)某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù),本文主要是對(duì)后端數(shù)據(jù)脫敏實(shí)現(xiàn)的簡(jiǎn)單總結(jié),希望對(duì)大家有所幫助2023-07-07IDEA 的基本介紹使用及斷點(diǎn)調(diào)試技巧
IDEA 是 JetBrains 公司的產(chǎn)品,總部位于捷克的首都布拉格,IDEA在業(yè)界被公認(rèn)為最好的 Java 開發(fā)工具,今天通過本文給大家介紹IDEA 的基本介紹使用及斷點(diǎn)調(diào)試技巧,感興趣的朋友跟隨小編一起看看吧2021-11-11Spring Boot Actuator端點(diǎn)相關(guān)原理解析
這篇文章主要介紹了Spring Boot Actuator端點(diǎn)相關(guān)原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07解決SpringBoot運(yùn)行報(bào)錯(cuò):找不到或無法加載主類的問題
這篇文章主要介紹了解決SpringBoot運(yùn)行報(bào)錯(cuò):找不到或無法加載主類的問題,具有很好的參考價(jià)值,對(duì)大家的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下2023-09-09Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(64)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-09-09springboot+mybatis配置clickhouse實(shí)現(xiàn)插入查詢功能
這篇文章主要介紹了springboot+mybatis配置clickhouse實(shí)現(xiàn)插入查詢功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08springmvc使用@notNull注解驗(yàn)證請(qǐng)求參數(shù)方式
這篇文章主要介紹了springmvc使用@notNull注解驗(yàn)證請(qǐng)求參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教<BR>2024-01-01