美文网首页
AQS源码解析(2)addWaiter

AQS源码解析(2)addWaiter

作者: 三斤牛肉 | 来源:发表于2021-01-06 11:44 被阅读0次

上一节的acquireQueued(addWaiter(Node.EXCLUSIVE), arg))函数中有一个addWaiter函数,表示将当前线程加入到排队队列中

//这个函数比较简单,就是将node放到队列末尾,mode表示是独占锁还是共享锁以后再讨论
private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {//如果tail不是null,表示队列已被初始化则将node 放到队尾
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {//cas将tail指向node,如果cas失败表示有多个线程都要放到队尾,这个时候会走到enq函数,该还是会再去cas放到队尾
                pred.next = node;
                return node;
            }
        }

        enq(node);        //初始化队列或者再次cas队尾
        return node;
 }
//该函数会初始化队列(如果队列未被初始化)
private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize  初始化队列
                if (compareAndSetHead(new Node())) //将head设置为一个空node。这个空node很重要,aqs的队头一定是空节点,用来表示正在执行的那个线程,想一下当执行线程结束后只有这个空节点才能去唤醒下一个节点,假如队头节点就是等待线程,谁能去唤醒他呢
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {//cas队尾,如果还失败看到这个是死循环会一直去放,直到放到队尾为止
                    t.next = node;
                    return t;
                }
            }
        }
    }

读完这2个函数有个疑问,是不是可以直接缩减成1个函数,addWaiter中cas那段和enq是一样的。

相关文章

网友评论

      本文标题:AQS源码解析(2)addWaiter

      本文链接:https://www.haomeiwen.com/subject/ikjnoktx.html