1、源码装修
1.1 hasQueuedPredecessors()解析
https://blog.csdn.net/weixin_38106322/article/details/107154961
public final boolean hasQueuedPredecessors() {// The correctness of this depends on head being initialized// before tail and on head.next being accurate if the current// thread is first in queue.Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());}
第一个判断等于这个方法:
head == tail要么是一起为null, 要么一起为虚拟头节点
head != tail表示队列中至少有两个不同节点存在,还有一种情况下面🌈处说明!
/***查询是否有线程在等待获取。 请注意,由于中断和超时导致的取消随时可能发生,*true返回并不能保证任何其他线程将永远获得。*在此实现中,此操作以恒定时间返回。* 返回:如果可能有其他线程等待获取,则为true**/public final boolean hasQueuedThreads() {return head != tail;}
所以会有很多种情况
hasQueuedPredecessors — true
- 两边都为true
head != tail 表示队列中至少有两个不同节点存在。
(s = h.next) == null || s.thread != Thread.currentThread() — 任意一边为true
- 🌈head != tail && (s = h.next) == null 这种特殊情况是处于下面图的这个位置:

那说明已经有节点尝试插入队列,根据FIFO的原理,我们这里应该是要排队
- (s = h.next) == null 为fasle — 》s.thread != Thread.currentThread() 为true
就是后继节点不是当前线程,所以也需要排队.
hasQueuedPredecessors — false
- h != t 为 false
即要么队列为空,头尾节点都会null;要么当h和t都指向同一个Node,也返回false。此时说明队列中只有一个dummy node,那说明没有线程在队列中。— 其实这里我认为有问题 ps:这种情况其实就是下面这两步执行好,可能原本的线程还在enq方法中自旋插入到同步等待队列,跟上面🌈处一样的道理,这里应该也需要排队.
if (compareAndSetHead(new Node()))tail = head;
- h != t 为 true, (s = h.next) == null || s.thread != Thread.currentThread()为false
取非转换: (s = h.next) != null && s.thread == Thread.currentThread()
表示是当前节点排在后面,所以不用排队.
