AQS 为什么从后往前遍历寻找继任者

https://blog.csdn.net/weixin_38038479/article/details/111915280

在阅读AQS源码的过程中,也许会存在这样的困惑,为什么当next指针对应的节点为null 或者取消时,从tail 向前遍历寻找最近的一个非取消的节点;

当前任释放时,需要获取继任者;AQS的实现方式是从tail 向前遍历,之所以这样是与入队时的逻辑有关;
见注释

  /**
     * Inserts node into queue, initializing if necessary. See picture above.
     * @param node the node to insert
     * @return node's predecessor
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                // 假设线程1执行到这里被挂起,此时 next 指针还没有关联到,后新来的线程 n 可能已经被排列到后面去了,所以当 t 被需要时,它的 next 指针还没有设置或者重置;故需要从后到前寻找,而如果找寻下一个,而这个可能被遗漏了;
                // 故api文档中有这样一说 (Or, said differently, the next-links are an optimization so that we don't usually need a backward scan.)
                    t.next = node;
                    return t;
                }
            }
        }
    }

源码内部类Node上的注释中有对这个场景的完整描述:

 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
         * 因为cas 入队时可能失败。
         * 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
         * 除非cas 失败(这不太可能),所以我们不会遍历太多
         * there, so we hardly ever traverse much.
         */
        return findNodeFromTail(node);

另一方面如果下一个节点时null(已经被GC ),如何找到下一个有效节点,也只能从后往前找了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值