ReentrantLock爲獨佔鎖,也即排他鎖,同一時刻只能有一個線程持有鎖。現在來看幾種共享鎖。
CountDownLatch
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
private final Sync sync;
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
//設置資源總數
setState(count);
}
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 zero
for (;;) {
//1、獲取當前資源數
int c = getState();
if (c == 0)
return false;
//2、釋放一個資源
int nextc = c-1;
//3、CAS更新資源數
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
生成CountDownLatch時需要傳入資源總數,代表所有線程總共享有這麼多資源。Sync爲一個實現了AQS的內部類,代理CountDownLatch的獲取和釋放操作。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void countDown() {
sync.releaseShared(1);
}
線程調用countDown時,最終調用Sync中的tryReleaseShared,將總資源減1。調用await時,最終調用Sync中tryAcquireShared,看資源是否全部釋放完。
需要所有線程等待某個條件完成後,才執行某個動作時,可以使用CountDownLatch。