原文链接:https://blog.csdn.net/weixin_38106322/article/details/107154961
hasQueuedPredecessors()方法源码如下:
public final boolean hasQueuedPredecessors() {
//读取头节点
Node t = tail;
//读取尾节点
Node h = head;
//s是首节点h的后继节点
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
这里先说一下hasQueuedPredecessors()方法的作用,主要是用来判断线程需不需要排队,因为队列是FIFO的,所以需要判断队列中有没有相关线程的节点已经在排队了。有则返回true表示线程需要排队,没有则返回false则表示线程无需排队。
结果一: 返回false,不需要排队
情况一: h != t返回false,那么短路与判断就会直接返回false
说明:当头节点和尾节点相等时,才会返回false。
头节点和尾节点都为null,表示队列都还是空的,甚至都没完成初始化,那么自然返回fasle,无需排队。
头节点和尾节点不为null但是相等,说明头节点和尾节点都指向一个元素,表示队列中只有一个节点,这时候自然无需排队,因为队列中的第一个节点是不参与排队的,它持有着同步状态,那么第二个进来的节点就无需排队,因为它的前继节点就是头节点,所以第二个进来的节点就是第一个能正常获取同步状态的节点,第三个节点才需要排队,等待第二个节点释放同步状态。
情况二:h != t返回true,(s = h.next) == null返回false以及s.thread !=
Thread.currentThread()返回false
说明:h != t返回true表示队列中至少有两个不同节点存在。
(s = h.next) == null返回false表示头节点是有后继节点的。
s.thread != Thread.currentThread()返回fasle表示着当前线程和后继节点的线程是相同的,那就说明已经轮到这个线程相关的节点去尝试获取同步状态了,自然无需排队,直接返回fasle。
结果二.返回true
情况一: h != t返回true,(s = h.next) == null返回true
h != t返回true表示队列中至少有两个不同节点存在。
(s = h.next) == null返回true,说明头节点之后是没有后继节点的,这情况可能发生在如下情景:有另一个线程已经执行到初始化队列的操作了,介于compareAndSetHead(new Node())与tail = head之间,如下:
这时候头节点不为null,而尾节点tail还没有被赋值,所以值为null,所以会满足h != t结果为true的判断,以及头节点的后继节点还是为null的判断,这时候可以直接返回true,表示要排队了,因为在当前线程还在做尝试获取同步状态的操作时,已经有另一个线程准备入队了,当前线程慢人一步,自然就得去排队。
情况二:h != t返回true,(s = h.next) == null返回false,s.thread !=
Thread.currentThread()返回true。
h != t返回true表示队列中至少有两个不同节点存在。
(s = h.next) == null返回false表示首节点是有后继节点的。
s.thread != Thread.currentThread()返回true表示后继节点的相关线程不是当前线程,所以首节点虽然有后继节点,但是后继节点相关的线程却不是当前线程,那当前线程自然得老老实实的去排队