Java 併發程式設計(十三) -- CountDownLatch原始碼分析

我很醜發表於2020-03-16

1. 類的定義

public class CountDownLatch
複製程式碼

2. 欄位屬性

//同步器,是AbstractQueuedSynchronizer的子類
private final Sync sync;
複製程式碼

從欄位屬性可以看出

  • CountDownLatch的核心是內部類Sync,可以猜測出所有的操作都是通過Sync物件來操作的

3. 構造方法

public CountDownLatch(int count) {
    	//引數檢查
        if (count < 0) throw new IllegalArgumentException("count < 0");
    	//初始化Sync
        this.sync = new Sync(count);
    }
複製程式碼

從構造方法中可以看出

  • 構造方法只做了一件事就是初始化Sync物件

4. 方法

await 方法

//等待,直到count到0再執行,或者執行緒被中斷
public void await() throws InterruptedException {
    	//呼叫sync的acquireSharedInterruptibly方法進入等待
        sync.acquireSharedInterruptibly(1);
    }
//設定超時時間的等待
public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
    	//呼叫sync的tryAcquireSharedNanos方法進入等待
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
複製程式碼

countDown 方法

//count 減1
public void countDown() {
    	//呼叫sync的releaseShared方法
        sync.releaseShared(1);
    }
複製程式碼

getCount 方法

//獲取count
public long getCount() {
    	//呼叫sync的getCount
        return sync.getCount();
    }
複製程式碼

toString 方法

public String toString() {
    	//可以看出列印了count的值
        return super.toString() + "[Count = " + sync.getCount() + "]";
    }
複製程式碼

從方法中可以看出Sync物件是一個共享鎖

5. 內部類Sync

1. 類的定義

private static final class Sync extends AbstractQueuedSynchronizer
複製程式碼

從類的定義中可以看出

  • Sync是CountDownLatch私有的靜態內部類
  • Sync繼承了AbstractQueuedSynchronizer

2. 欄位屬性

//序列化版本號
private static final long serialVersionUID = 4982264981922014374L;
複製程式碼

3. 構造方法

//傳入count
Sync(int count) {
    		//呼叫父類的setState方法
            setState(count);
        }
複製程式碼

從構造方法可以看出

  • 傳入的count就是AbstractQueuedSynchronizer的state方法

4. 方法

getCount 方法
//獲取count,實際上就是獲取state
int getCount() {
            return getState();
        }
複製程式碼
tryAcquireShared 方法
//嘗試獲取共享鎖,重寫父類方法,這個方法是讓父類呼叫
protected int tryAcquireShared(int acquires) {
    		//如果state為0,返回1, 其他的返回-1
    		//小於0會嘗試獲取鎖,如果獲取鎖失敗則會進入佇列等待被喚醒
            return (getState() == 0) ? 1 : -1;
        }
複製程式碼
tryReleaseShared 方法
//釋放共享鎖,這個引數沒有意義,每次通過CAS自旋的方法讓state-1
protected boolean tryReleaseShared(int releases) {
            //無限for迴圈表示自旋
            for (;;) {
                //獲取狀態值
                int c = getState();
                //如果狀態值為0, 表示已經完全釋放鎖了,直接返回false
                if (c == 0)
                    return false;
                //狀態值不為0,讓狀態值-1,並用CAS設定新值
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
複製程式碼

相關文章