CountDownLatch 源码分析
1. 類介紹
一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。用給定的計數 初始化 CountDownLatch。由于調用了 countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之后,會釋放所有等待的線程,await 的所有后續調用都將立即返回。這種現象只出現一次——計數無法被重置。
2. 使用場景
在一些應用場合中,需要等待某個條件達到要求后才能做后面的事情。
CountDownLatch最重要的方法是countDown()和await()兩個方法,countDown主要是倒數一次,await是等待倒數到0,如果沒有到達0,就只有阻塞等待了。
例如:
A 和 B 相約一起吃飯,等A和B都到指定頂點后才能開始吃飯,下面用代碼模擬實現。
示例
public class CountDownLatchTest {static CountDownLatch c = new CountDownLatch(2);public static void main(String[] args) {new Thread(new Runnable() {public void run() {System.out.println("A 我來了");c.countDown();}}).start();new Thread(new Runnable() {public void run() {System.out.println("B 我來了");c.countDown();}}).start();new Thread(new Runnable() {public void run() {try {c.await();System.out.println("開始吃飯...");} catch (InterruptedException e) {e.printStackTrace();}}}).start();} }源碼分析:
需要提前了解:AbstractQueuedSynchronizer 源碼分析
AQS提供了兩種模式:獨占模式&共享模式。CountDownLatch就是一個使用共享模式的自定義同步器實現的共享鎖。
CountDownLatch 代碼不多,主要是通過內部類繼承AQS來實現其功能的,下面我們一步一步來分析下源碼:
Sync 內部類
private static final class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 4982264981922014374L;//構造Sync對象是初始化AQS中state的數量(共享鎖的個數)Sync(int count) {setState(count);}//獲取當前state的數量(共享鎖個數)int getCount() {return getState();}//嘗試獲得獲得鎖protected int tryAcquireShared(int acquires) {return (getState() == 0) ? 1 : -1;}//嘗試釋放鎖protected boolean tryReleaseShared(int releases) {// Decrement count; signal when transition to zerofor (;;) {int c = getState();if (c == 0)return false;int nextc = c-1;if (compareAndSetState(c, nextc))return nextc == 0;}} }AbstractQueuedSynchronizer 類采用模版模式進行擴展實現其相應的功能。子類只需要實現
如下5個方法就能實現其不同功能的鎖。
而CountDownLatch 的內部類Sync使用的是共享鎖所以只實現了tryAcquireShared和tryReleaseShared方法。
CountDownLatch的構造方法
public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count); }創建CountDownLatch對象時,需要傳入一個int的計數器。
await 方法
public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1); }public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); }await方法調用AQS的獲得鎖的方法,只有AQS的state狀態為0時才能獲得鎖,如果state不為0,則需要在AQS的等待隊列中阻塞等待。
public void countDown() {sync.releaseShared(1); }countDown方法則調用AQS的releaseShared方法,釋放共享鎖,也就是每次將state狀態每次減一,直到減到0,則喚醒隊列中的所有節點(線程)。
public long getCount() {return sync.getCount(); }獲取計數器當前值。
本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點擊這里快速進入簡書
總結
以上是生活随笔為你收集整理的CountDownLatch 源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AbstractQueuedSynchr
- 下一篇: Semaphore 源码分析