Java 如何理解“;isOnSyncQueue”;AQS的功能
当我阅读Java关于AQS(AbstractQueuedSynchronizer)的源代码时,我有一个疑问Java 如何理解“;isOnSyncQueue”;AQS的功能,java,multithreading,concurrency,Java,Multithreading,Concurrency,当我阅读Java关于AQS(AbstractQueuedSynchronizer)的源代码时,我有一个疑问 final boolean isOnSyncQueue(Node node) { if (node.waitStatus == Node.CONDITION || node.prev == null) return false; if (node.next != null) // If has successor, it must be on queue
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
return findNodeFromTail(node);
}
最主要的疑问是最后一条注释。当一个等待条件的线程被另一个调用signal()
方法的线程通知时,它的节点已经进入同步队列
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
如果另一个线程没有完全执行enq(Node)
方法,则此节点将一致地尝试compareAndSetTail(oldTail,Node)
,直到成功。执行完成后,可能会通知此线程
我可以想象这样一种情况,当enq
方法调用时,这个线程是“意外唤醒”,并执行isOnSyncQueue
方法。此时它的waitStatus not条件和prev设置为'enq',因此它可以满足注释所述。但是,由于节点CAS失败,调用findNodeFromTail
方法时,它不在同步队列中。findNodeFromTail
没有意义
当enq
invoke成功,并且prev节点被取消时,它将取消该线程的连接,但是该线程被意外唤醒,isOnSyncQueue
方法返回false,该线程再次被阻塞。在这个时候,它将不再是信号
if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
下面是我说的(我不允许浏览图片):
那么,我说的对吗?或者你可以告诉我为什么?谢谢你的回答
thread1: transferForSignal() enq()
thread2: surprise wake up. execute isOnSyncQueue() and return fasle
thread1: enq() execute finish and prev is cancelled or CAS fail,
LockSupport.unpark(node.thread), this is make no sense.
thread2: LockSupport.park(this) and won't be signalled because
LockSupport.unpark(node.thread) has been invoked.