java aqs中什么情况下会调用cancelAcquire方法

//阻塞当前线程,等待被唤醒,

final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true; //true代表成功获取锁
    try {
        boolean interrupted = false;  //线程在等待过程中是否被中断
        for (;;) {
            final Node p = node.predecessor();

   //为什么在执行tryAcquire()需要先判断p==head?

   //p==head如果为true说明node为等待队列中的队首节点,也就是说一旦线程进了等待队列后,

//获取锁的顺序也是从前往后,跟公平锁这里的逻辑一致

//综上:公平和非公平区别是线程在执行lock()后,公平锁则会判断等待队列中是否有其他线程,如果有,就没资格获取锁,入

//队尾等待被唤醒,如果是非公平锁,则直接尝试获取锁,如果获取锁成功执行自己业务,

//否则也被加入队尾等待被唤醒。至于唤醒的顺序,两者保持一致,都是从head开始往后排
            if (p == head && tryAcquire(arg)) {
                setHead(node); //出队,head后移
                p.next = null; // help GC
                failed = false;
                return interrupted;
            }
            if (shouldParkAfterFailedAcquire(p, node) &&  //判断当前线程在获取锁失败后是否应该阻塞自己
                parkAndCheckInterrupt()) //park自己后,当前线程无限期等待中......被唤醒,返回当前线程的中断标志位并清除
                //如果检测到线程被打上了中断标识,并不会立即抛出中断异常,而是等到获取锁返回后重新打上中断标识,

//aqs中的doAcquireInterruptibly()方法是立即抛出中断异常

interrupted = true;  //线程在处于等待期间被中断
        }
    } finally {

//LockSuport.park();等待,响应中断,但是并不会抛出任何InterruptedException异常,意味着如果线程在等待

//期间被中断,则立即进入阻塞状态,且不会清除线程的中断标识,如果再次调用park则不会进入等待状态,

//需要再次清除线程的中断标志位则可以

//wait join sleep都响应中断,并抛出中断异常后清除中断标志位

//park响应中断,并不会抛出中断异常,也不会清除中断标志位                  
        if (failed)

   //何时会进入该方法????
            cancelAcquire(node);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_33436466/article/details/107901204