page contents

CountDownLatch源码求解

Pack 发布于 2020-02-11 17:39
阅读 544
收藏 0

//带有阻塞获得共享锁

 private void doAcquireSharedInterruptibly(int arg)

        throws InterruptedException {

        final Node node = addWaiter(Node.SHARED);

        boolean failed = true;

        try {

            for (;;) {

                final Node p = node.predecessor();

                if (p == head) {

                    int r = tryAcquireShared(arg);

                    if (r >= 0) {

                        setHeadAndPropagate(node, r);

                        p.next = null; // help GC

                        failed = false;

                        return;

                    }

                }

                if (shouldParkAfterFailedAcquire(p, node) &&

                    parkAndCheckInterrupt())

                    throw new InterruptedException();

            }

        } finally {

            if (failed)

                cancelAcquire(node);

        }

    }

//设置头节点并向下传播

private void setHeadAndPropagate(Node node, int propagate) {

        Node h = head; // Record old head for check below

        setHead(node);

        if (propagate > 0 || h == null || h.waitStatus < 0 ||

            (h = head) == null || h.waitStatus < 0) {

            Node s = node.next;

            if (s == null || s.isShared())

                doReleaseShared();

        }

    }


//释放共享锁

private void doReleaseShared() {

        for (;;) {

            Node h = head;

            if (h != null && h != tail) {

                int ws = h.waitStatus;

                if (ws == Node.SIGNAL) {

                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))

                        continue;            // loop to recheck cases

                    unparkSuccessor(h);

                }

                else if (ws == 0 &&

                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))

                    continue;                

            }

            if (h == head)                  

                break;

        }

    }


问题 :关于CountDownLatch中aqs同步队列的最后一个节点的生命周期

当我们调用addWaiter通过cas向尾部插入node,waitStatus=0,最后一个节点

被唤醒时(其他线程countDown后state =0 ),阻塞线程被唤醒setHeadAndPropagate -> doReleaseShared,因为是最后一个节点waitStatus=0 所以进入到if(h==head)跳出自旋,这个时候头节点没有被回收的,问:当没有其他线程在向aqs 添加节点,当前的头节点的生命周期就和aqs生命周期保持一致了,这样理解正确么?


下面附上一张流程图

attachments-2020-02-xKcSA1Lf5e427651dde42.png
329
Pack
Pack

是的,没错

请先 登录 后评论