Semaphore 是什么?
Semaphore 糯而,是一種新的同步類天通,它是一個(gè)計(jì)數(shù)信號。從概念上講熄驼,從概念上講像寒,信號量維護(hù)了一個(gè)許可集合。
- 如有必要瓜贾,在許可可用前會(huì)阻塞每一個(gè)
#acquire()
方法诺祸,然后再獲取該許可。 - 每個(gè)
#release()
方法祭芦,添加一個(gè)許可筷笨,從而可能釋放一個(gè)正在阻塞的獲取者。 - 但是,不使用實(shí)際的許可對象胃夏,Semaphore 只對可用許可的數(shù)量進(jìn)行計(jì)數(shù)轴或,并采取相應(yīng)的行動(dòng)。
信號量常常用于多線程的代碼中构订,比如數(shù)據(jù)庫連接池侮叮。
- 使用方式,可以看看 《JAVA多線程 – 信號量(Semaphore)》 悼瘾。
- 源碼解析囊榜,可以看看 《【死磕 Java 并發(fā)】—– J.U.C 之并發(fā)工具類:Semaphore》 。
說說 CountDownLatch 原理
CountDownLatch 亥宿,字面意思是減小計(jì)數(shù)(CountDown)的門閂(Latch)卸勺。它要做的事情是,等待指定數(shù)量的計(jì)數(shù)被減少烫扼,意味著門閂被打開曙求,然后進(jìn)行執(zhí)行。
CountDownLatch 默認(rèn)的構(gòu)造方法是 CountDownLatch(int count)
映企,其參數(shù)表示需要減少的計(jì)數(shù)悟狱,主線程調(diào)用 #await()
方法告訴 CountDownLatch 阻塞等待指定數(shù)量的計(jì)數(shù)被減少,然后其它線程調(diào)用 CountDownLatch 的 #countDown()
方法堰氓,減小計(jì)數(shù)(不會(huì)阻塞)挤渐。等待計(jì)數(shù)被減少到零,主線程結(jié)束阻塞等待双絮,繼續(xù)往下執(zhí)行浴麻。
- CountDownLatch 的使用示例,請看 《Java 多線程 CountDownLatch 用法》 囤攀。
- CountDownLatch 的源碼解析软免,請看 《【死磕 Java 并發(fā)】—– J.U.C 之并發(fā)工具類:CountDownLatch》
說說 CyclicBarrier 原理
CyclicBarrier ,字面意思是可循環(huán)使用(Cyclic)的屏障(Barrier)焚挠。它要做的事情是膏萧,讓一組線程到達(dá)一個(gè)屏障(也可以叫同步點(diǎn))時(shí)被阻塞,直到最后一個(gè)線程到達(dá)屏障時(shí)蝌衔,屏障才會(huì)開門榛泛,所有被屏障攔截的線程才會(huì)繼續(xù)干活。
CyclicBarrier 默認(rèn)的構(gòu)造方法是 CyclicBarrier(int parties)
胚委,其參數(shù)表示屏障攔截的線程數(shù)量挟鸠,每個(gè)線程調(diào)用 #await()
方法告訴 CyclicBarrier 我已經(jīng)到達(dá)了屏障叉信,然后當(dāng)前線程被阻塞亩冬,直到 parties
個(gè)線程到達(dá),結(jié)束阻塞。
- CyclicBarrier 的使用示例硅急,請看 《CyclicBarrier 的用法》
- CyclicBarrier 的源碼解析覆享,請看 《【死磕 Java 并發(fā)】—- J.U.C 之并發(fā)工具類:CyclicBarrier》 。
說說 Exchanger 原理
實(shí)際場景下营袜,問了一圈朋友撒顿,Exchanger 基本沒在業(yè)務(wù)中使用過。
- Exchanger 的使用示例荚板,請看 《【Java并發(fā)】線程同步工具Exchanger的使用》 凤壁。
- Exchanger 的源碼解析,請看 《【死磕 Java 并發(fā)】—– J.U.C 之并發(fā)工具類:Exchanger》
CyclicBarrier 和 CountdownLatch 有什么區(qū)別跪另?
CyclicBarrier 可以重復(fù)使用拧抖,而 CountdownLatch 不能重復(fù)使用。
- CountDownLatch 其實(shí)可以把它看作一個(gè)計(jì)數(shù)器免绿,只不過這個(gè)計(jì)數(shù)器的操作是原子操作唧席。
- 你可以向 CountDownLatch 對象設(shè)置一個(gè)初始的數(shù)字作為計(jì)數(shù)值,任何調(diào)用這個(gè)對象上的
#await()
方法都會(huì)阻塞嘲驾,直到這個(gè)計(jì)數(shù)器的計(jì)數(shù)值被其他的線程減為 0 為止淌哟。所以在當(dāng)前計(jì)數(shù)到達(dá)零之前,await 方法會(huì)一直受阻塞辽故。之后徒仓,會(huì)釋放所有等待的線程,await 的所有后續(xù)調(diào)用都將立即返回榕暇。這種現(xiàn)象只出現(xiàn)一次——計(jì)數(shù)無法被重置蓬衡。如果需要重置計(jì)數(shù),請考慮使用 CyclicBarrier 彤枢。 - CountDownLatch 的一個(gè)非常典型的應(yīng)用場景是:有一個(gè)任務(wù)想要往下執(zhí)行狰晚,但必須要等到其他的任務(wù)執(zhí)行完畢后才可以繼續(xù)往下執(zhí)行。假如我們這個(gè)想要繼續(xù)往下執(zhí)行的任務(wù)調(diào)用一個(gè) CountDownLatch 對象的
#await()
方法缴啡,其他的任務(wù)執(zhí)行完自己的任務(wù)后調(diào)用同一個(gè) CountDownLatch 對象上的#countDown()
方法壁晒,這個(gè)調(diào)用#await()
方法的任務(wù)將一直阻塞等待,直到這個(gè) CountDownLatch 對象的計(jì)數(shù)值減到 0 為止业栅。
- 你可以向 CountDownLatch 對象設(shè)置一個(gè)初始的數(shù)字作為計(jì)數(shù)值,任何調(diào)用這個(gè)對象上的
- CyclicBarrier 一個(gè)同步輔助類秒咐,它允許一組線程互相等待,直到到達(dá)某個(gè)公共屏障點(diǎn) (common barrier point)碘裕。在涉及一組固定大小的線程的程序中携取,這些線程必須不時(shí)地互相等待,此時(shí) CyclicBarrier 很有用帮孔。因?yàn)樵?barrier 在釋放等待線程后可以重用雷滋,所以稱它為循環(huán)的 barrier 不撑。
整理表格如下:
CountDownLatch | CyclicBarrier |
---|---|
減計(jì)數(shù)方式 | 加計(jì)數(shù)方式 |
計(jì)算為 0 時(shí)釋放所有等待的線程 | 計(jì)數(shù)達(dá)到指定值時(shí)釋放所有等待線程 |
計(jì)數(shù)為 0 時(shí),無法重置 | 計(jì)數(shù)達(dá)到指定值時(shí)晤斩,計(jì)數(shù)置為 0 重新開始 |
調(diào)用 #countDown() 方法計(jì)數(shù)減一焕檬,調(diào)用 #await() 方法只進(jìn)行阻塞,對計(jì)數(shù)沒任何影響 |
調(diào)用 #await() 方法計(jì)數(shù)加 1 澳泵,若加 1 后的值不等于構(gòu)造方法的值实愚,則線程阻塞 |
不可重復(fù)利用 | 可重復(fù)利用 |