//阻塞当前线程,等待被唤醒,
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);
}
}