CountDownLatch
闭锁:
阻塞几个线程,直到某些线程的任务执行完成后,才会唤醒被阻塞线程,
await 方法的实现:
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); }
1) AQS中的 acquireSharedInterruptibly 方法
public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) // 如果当前线程的中断状态为true, 抛出异常 throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); }
2)Count中的 Sync的 tryAcquireShared 方法
protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; // state的值不等于0才会返回 -1 }
3)AQS 中的 doAcquireSharedInterruptibly 方法
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node.SHARED); // 入队 共享锁 boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); // 当state为0时,返回1,否则返回-1; if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) // 阻塞(挂起)当前线程 throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } }
AQS中的
private void setHeadAndPropagate(Node node, int propagate) { Node h = head; // Record old head for check below setHead(node); /* * Try to signal next queued node if: * Propagation was indicated by caller, * or was recorded (as h.waitStatus either before * or after setHead) by a previous operation * (note: this uses sign-check of waitStatus because * PROPAGATE status may transition to SIGNAL.) * and * The next node is waiting in shared mode, * or we don't know, because it appears null * * The conservatism in both of these checks may cause * unnecessary wake-ups, but only when there are multiple * racing acquires/releases, so most need signals now or soon * anyway. */ if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) { Node s = node.next; if (s == null || s.isShared()) doReleaseShared(); } }
countDown的实现:
public void countDown() { sync.releaseShared(1); }
1) AQS 中的 releaseShared 方法。
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { // 执行 该方法后,state的值正好为0 时,才为true;(也就是当前state的值为1时,减1后,会返回true) doReleaseShared(); return true; } return false; }
2)CountDown中的 tryReleaseShared 方法
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; // 将state的值减1 if (compareAndSetState(c, nextc)) return nextc == 0; } }
3) AQS 中的 doReleaseShared 方法
private void doReleaseShared() { /* * Ensure that a release propagates, even if there are other * in-progress acquires/releases. This proceeds in the usual * way of trying to unparkSuccessor of head if it needs * signal. But if it does not, status is set to PROPAGATE to * ensure that upon release, propagation continues. * Additionally, we must loop in case a new node is added * while we are doing this. Also, unlike other uses of * unparkSuccessor, we need to know if CAS to reset status * fails, if so rechecking. */ for (;;) { Node h = head; if (h != null && h != tail) { // 阻塞队列(CLH)中有node结点 int ws = h.waitStatus; if (ws == Node.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; } }
也许会有遗憾,但是不应该在失败之前
浙公网安备 33010602011771号