AQS源码解析(8)Condition.await

Condition条件锁,当线程获得锁之后,可以在指定的Condition上等待或被唤醒
核心函数await:

public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();//将当前线程放到等待队列队尾,类似aqs的head,tail操作,还比较简单就不看了
            int savedState = fullyRelease(node);//因为await和signal必须在lock内部执行,所以此时必定持有锁,所以要释放当前线程持有的锁,看下面
            int interruptMode = 0;

            //这个while很有意思,之前说await必定已经获得到锁,
            //那么一定不在aqs的等待队列中(注意condition有2个队列一个是aqs的等待队列,一个是condition维护的wait队列)
            //好,如果不在!isOnSyncQueue(node)返回的是true(注意前面的!),
            //然后进入循环,线程挂起。
            //等到某一天有一个线程调用的signal或signalAll函数,当前线程被唤醒,继续往下执行。
            //然后再进入while循环判断,这个时候当前线程会被移到aqs等待队列中(具体在signal函数中以后分析),跳出循环
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                //这里判断在park的时候线程有没有被打断过(即调用interrupte()函数)如果被打断过则跳出
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            //这里其实跟acquire一样先cas一次去尝试获得锁,然后挂起线程
            //这里的挂起是等待队列的挂起,不是wait的挂起
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            //将cancel的线程从wait队列中移除掉
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                //响应打断
                reportInterruptAfterWait(interruptMode);
}

final int fullyRelease(Node node) {
        boolean failed = true;
        try {
            int savedState = getState();//获得当前重入锁计数器,当调用acquire()成功的时候会获得锁并将计数器+1,再次调用的时候只增加计数器,具体在https://www.jianshu.com/p/a8e53a694468讲过
            if (release(savedState)) {//这里要把所有的计数器都释放掉,这也就表示await是释放锁的,还记得object.wait()是怎么说明的么,同样也会释放锁。笔者在https://www.jianshu.com/p/3748da0ee63c大概写过一些。
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

下一节将signal,await要结合signal一起看可能更清楚

你可能感兴趣的:(AQS源码解析(8)Condition.await)