aqs源码按行解析

158 阅读1分钟

1、入队列enq方法

/**
     * Inserts node into queue, initializing if necessary. See picture above.
     * @param node the node to insert(待插入的节点)
     * @return node's predecessor(前任节点)
     */
     //todo 当第一个节点入队列的时候需要debug查看情况
    private Node enq(final Node node) {
        for (;;) { //自旋
            Node t = tail; //临时的对象引用,指向尾节点
            //如果临时的对象引用为null,说明队列没有元素
            if (t == null) { // Must initialize 
                //cas设置头节点为 重写new的一个节点,设置成功或者失败都再次循环,因为没返回值 
                if (compareAndSetHead(new Node()))
                    tail = head; //设置头节点成功,将头节点赋值给尾节点,此时都节点和尾节点都指向当前入参节点,但是节点没建立关系
            } else { //尾节点不为null
                node.prev = t; //将当前节点的前任节点设置为尾节点(即插入到队列的尾部)
                if (compareAndSetTail(t, node)) {//cas设置尾节点为当前节点,设置失败再次循环
                    t.next = node; //将之前的尾巴节点(t,即现在队列的倒数第二个节点),t的下一个节点指向新的尾巴节点(即当前入参节点node)
                    return t; //返回前任节点
                }
            }
        }
    }

aqs-enq.png