关于hasQueuedPredecessors的理解

hasQueuedPredecessors

  1. 关于这个一直没绕明白,今天看到这个文章瞬间明白了,记录一下
public final boolean hasQueuedPredecessors() {
        Node t = tail; 
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

返回:

  1. true:如果当前线程前面有排队等待的线程
  2. false:如果当前线程是第一个等待获取锁的线程(即,一般就是head.next);或者等待队列为空。

该方法的正确性依赖于head在tail之前被初始化,以及head.next的精确性,如果当前线程是队列中第一个等待获取锁的线程的时候。

① tail节点的获取一定先于head节点的获取。因为head节点的初始化在tail节点之前,那么基于当前的tail值,你一定能获取到有效的head值。这么做能保证接下来流程的正确性。举个反例来说明这么做的必要性:如果你按『Node h = head; Node t = tail;』的顺序来对h、t进行赋值,那么可能出现你在操作这两步的时候有其他的线程正在执行队列的初始化操作,那么就可能的带一个『h == null』,而『tail!=null』的情况(这种情况下,是不对的,因为tail!=null的话,head一定也不为null了),这使得『h != t』判断为true,认为当下是一个非空的等待队列,那么接着执行『s = h.next』就会抛出NPE异常了。但是当『Node t = tail; Node h = head;』按初始化相反的顺序来赋值的话,则不会有问题,因为我们保证了在tail取值的情况下,head的正确性。我们接下看下面的步骤,来说明为什么这么做就可以了。

② 在获取完t、h之后,我们接着先判断『h != t』,该判断的用意在于,判断当前的队列是否为空。如果为true则说明,当前队列非空。如果为false 则说明当前队列为空,为空的话,方法就直接结束了,并返回false。 但是请注意,当『h != t』为true时,其实是有两种情况的:

  • 当tail和head都非空时,说明此时等待队列已经完成了初始化,head和tail都指向了其队列的头和队列的尾。
  • 当“tail==null”同时“head !=
    null”,则说明,此时队列正在被其他线程初始化,当前我们获取的h、t是初始化未完成的中间状态。但是没关系,下面的流程会对此请进行判断。

③ 当『h != t』返回’true’的话,继续判断『(s = h.next) == null || s.thread ! = Thread.currentThread()』。这里的两个判断分别对应了两种情况:

  • 『(s = h.next) == null』返回’true’,则说明当获取的h、t为初始化的中间状态,因为第一个线程入队的时候,会先初始化队列,然后才对head的next值进行赋值,所以我们需要“s = h.next”是否为null进行判断,如果为’null’,则说明当前等待队列正在被初始化,并且有一个线程正在入队的操作中。所以此时方法直接结束,并且返回true。
  • 如果『h != t』并且『(s = h.next) !=null』,则说明当前线程已经被初始化好了,并且等待队列中的第一个等待获取锁的线程也已经入队了。那么接着我们就判断这个在等待队列中第一个等待获取锁的线程是不是当前线程『s.thread != Thread.currentThread()』。
    如果是的话,方法结束并返回false,表示当前线程前面没有比它等待更久获取这个锁的线程了;否则方法结束返回true,表示当前线程前面有比它等待更久希望获取这个锁的线程。

参考链接 ReentrantLock 源码浅析源码解析

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值