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 order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); }View Code
这个方法是用来判断线程是否需要排队的(返回false不需要排队),因为是公平锁,所以这个判断是必须的,否则就不公平了,因为没有判断排队操作,那么只要一个线程释放了锁,那么后来的线程也是可以抢到的(透露一下:非公平锁的实现就是仅仅少了这个判断而已)
公平锁竞争锁是否需要排队:
步骤如下:
判断头结点是否等于尾结点,只有在初始化的时候,头结点才会等于尾结点,或者队列为空,头尾结点都为null,所以,如果头结点等于尾结点(直接返回false),就代表了队列为空,所以就不需要进行排队
通过第一个判断就已经知道头尾结点之间是有其他结点存在的,但由于前面的enq方法是先处理头结点的,然后除了两个CAS操作之外,其他都不是原子性的,也就是基本上整个enq方法都不是原子性的,所以当正在插入第一个线程的时候,会出现一个h.next == null的问题(这时已经代表有一个线程正在插入了,但还没完成插入,所以当前线程需要排队),所以当h.next == null时就代表要排队
最后一个判断就是判断头结点的下一个线程是不是当前线程(也就是下一个是不是轮到你,不需要排队,因为插入方法是尾插法,所以弹出方法要从头弹出),经过前面两次判断,可以得知队列中有人在排队,并且此时并不存在队列第一次插入结点的Null问题,那么最后就需要判断下一个是否轮到当前线程
参考链接:
https://blog.csdn.net/AK774S/article/details/124664227
标签:结点,ReentrantLock,排队,next,竞争,判断,线程,null From: https://www.cnblogs.com/xdlrf/p/16925670.html