CountDownLatch原理分析 - 969251639/study GitHub Wiki

CountDownLatch可以让一个线程设置个卡住点,当CountDownLatch内的线程全部执行玩后这个线程才继续往下走

它的构造方法很简单:

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");//小于0抛出异常
        this.sync = new Sync(count);//通过count创造一个同步器
    }

另外它的内部用一个同步器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) {//尝试获取共享同步状态,如果同步状态数量为0,则表示获取成功,否则失败
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {//释放同步数量
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();//获取同步状态
                if (c == 0)//如果同步状态为0,表示没有任何线程占用同步状态,无需释放同步状态,返回false
                    return false;
                int nextc = c-1;//同步状态数量-1
                if (compareAndSetState(c, nextc))//cas更新同步数量
                    return nextc == 0;//如果同步数量减少到0,表示释放成功,反之失败
            }
        }
    }

Sync继承AbstractQueuedSynchronizer,实现它的共享模板方法
https://github.com/969251639/study/wiki/AbstractQueueSysnchorized%E5%8E%9F%E7%90%86

接下来看await的实现

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);//内部的AQS会自动调用tryAcquireShared来尝试获取同步状态
    }
    protected int tryAcquireShared(int acquires) {//尝试获取共享同步状态,如果同步状态数量为0,则表示获取成功,否则失败
        return (getState() == 0) ? 1 : -1;
    }

假如CountDownLatch的count为3,那么state的最大值为3,直到调用countDown,将state的值减到0,tryAcquireShared才会返回true

    public void countDown() {
        sync.releaseShared(1);//内部的AQS会自动调用tryReleaseShared来尝试释放同步状态
    }
    protected boolean tryReleaseShared(int releases) {//释放同步数量
        // Decrement count; signal when transition to zero
        for (;;) {
            int c = getState();//获取同步状态
            if (c == 0)//如果同步状态为0,表示没有任何线程占用同步状态,无需释放同步状态,返回false
                return false;
            int nextc = c-1;//同步状态数量-1
            if (compareAndSetState(c, nextc))//cas更新同步数量
                return nextc == 0;//如果同步数量减少到0,表示释放成功,反之失败
        }
    }