CountDownLatch
CountDownLatch的同步隊列結構:
雙向鏈表,其中,head是空節點new Node(),tail是最後一個線程node
await()方法解析
public void await() throws InterruptedException {
//調用AQS的模板方法
sync.acquireSharedInterruptibly(1);
}
/**
AQS的模板方法
*/
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
//一個死循環,直到tryAcquireShared成功
final Node p = node.predecessor();
if (p == head) {
//前驅節點是head,嘗試獲取鎖
//tryAcquireShared()是AQS子類實現的
int r = tryAcquireShared(arg);
if (r >= 0) {
//成功獲取,將node變成頭結點,循環退出的唯一條件
//並喚醒後續節點的線程,使後續節點能夠自旋檢測,即此for循環
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//shouldParkAfterFailedAcquire如果前驅節點是signal則返回true,否則將前驅節點設置成signal
//parkAndCheckInterrupt將線程掛起
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
/**
AQS子類即CountDownLatch內部類Sync實現的方法
*/
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
/*
將線程node加入鏈表
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
//如果tail不是null說明已經有node加入到隊列
//設置新加入的node的前驅是tail
node.prev = pred;
//新加入的node爲tail
if (compareAndSetTail(pred, node)) {
//讓node的前驅指向node
pred.next = node;
return node;
}
}
//尚未有node加入到隊列
enq(node);
return node;
}
/*
*
*/
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
//頭結點是空節點
if (compareAndSetHead(new Node()))
tail = head;
} else {
//空節點指向新建立的node
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
countDwon()方法解析
public void countDown() {
//減少1個state
sync.releaseShared(1);
}
/**
AQS的模板方法
*/
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
/**
Sync的釋放鎖方法
*/
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
private void doReleaseShared() {
for (;;) {
//頭結點是new Node() 空的
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
//頭結點是SIGNAL,說明需要喚醒其後續結點
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
//喚醒後續結點線程
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}