AQS源码分析之释放锁:release

209 阅读1分钟

1、release函数解析

1、如果获取锁成功,则判断head节点;
2、head为空,或者状态为0,说明锁没有被占用,直接返回true,
3、如果head不为空,且状态不为0,则调用 unparkSuccessor(h)函数,唤醒后继节点;

    public final boolean release(int arg) {
        //tryRelease分析地址:https://juejin.cn/post/6954983186426396708/
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

2、unparkSuccessor(Node node)函数解析

1、获取节点的状态,如果状态小于0,则设置为0(无状态);
2、获取node节点的后置节点next;
     2.1、如果next节点为空,或者状态大于0(取消状态),则next设置为null;
             从tail节点,向前查找,找到第一个非取消状态的node,即状态小于0的节点,
             将该节点设置为当前node的next节点;
     2.2、如果next节点不为空,则LockSupport.unpark(s.thread)唤醒next节点的线程;

    /**
     * Wakes up node's successor, if one exists.
     *
     * @param node the node
     */
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        Node s = node.next;
        if (s == null || s.waitStatus > 0) {
            s = null;
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }