1. Release function parsing

1. If the lock is obtained successfully, judge the head node; If head is empty or the state is 0, the lock has not been taken and returns true. If head is not empty and the state is not 0, call the unparksucceeded (h) function to wake up the succeeding nodes.

    public final boolean release(int arg) {
        / / tryRelease analysis address: https://juejin.cn/post/6954983186426396708/
        if (tryRelease(arg)) {
            Node h = head;
            if(h ! =null&& h.waitStatus ! =0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
Copy the code

Succeeded (Node Node

1. Get the node status. If the status is less than 0, set it to 0(stateless). 2. Obtain the next node of the node. 2.1. If next is empty, or the state is greater than 0(cancel state), next is set to null; From the tail node, look forward to find the first non-canceled node, that is, the node whose state is less than 0, and set that node to the next node of the current node. 2.2. If the next node is not empty, locksupport. unpark(s.read) wakes up the thread of the next node;

    /**
     * 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);
    }
Copy the code