美文网首页
AQS源码解析(8)Condition.await

AQS源码解析(8)Condition.await

作者: 三斤牛肉 | 来源:发表于2021-01-12 14:32 被阅读0次

    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

          本文链接:https://www.haomeiwen.com/subject/obyzoktx.html