ReentrantLock源码解析(二)

本篇博客深入源码分析 ReentrantLock 解锁过程

解锁相对于加锁,没有很复杂,这里要结合加锁时的阻塞位置,完整整个流程

public void unlock() {
    sync.release(1);
}

lock中的state记录锁的状态,加锁或者重入 state+1,那么解锁就是-1;所以整个解锁过程会有两种情况,state=1和state>1 重入

public final boolean release(int arg) {
    // 尝试解锁
    if (tryRelease(arg)) {
        //如果解锁成功,指的是不管加了多少层锁,最终都state==0,获取头节点,判断头节点不为null并且h.waitStatus != 0
        // 什么意思呢?ws在加锁过程中,入队的node会把prev的status设置为SIGNAL,如果h.waitStatus==0说明头节点空闲,或者说整个队列没有排队
        // unparkSuccessor的作用是唤醒线程,并且是优先级最高的,此时队列一定是排队的
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

分析上下两段代码,对于重入锁,每次解锁只会修改state的数值,修改到最后state==0时,才去做唤醒操作

protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    // 对于非重入来说,此时c==0,判断当前的线程是不是持有锁的线程,如果不是,抛异常
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        // 对于非重入,直接一步到这,清空持有线程为null,返回true
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

AbstractOwnableSynchronizer.java

protected final void setExclusiveOwnerThread(Thread thread) {
    exclusiveOwnerThread = thread;
}
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.
     */
     //这注释说的明明白白的,获取头节点的next,就是队列第一个排队的节点,如果是空,表示我不需要去unpark
     //如果不为空呢,我判断他是不是需要被唤醒的,如果是CANCEL,就是ws==1,就跳过;从后往前找排在最前边的ws<0的node,把它唤醒!
    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);
        // 注意这里,这里调用了unpark之后,会唤醒s,找到s park时的位置,也就是加锁过程中的parkAndCheckInterrupt()
        // interrupted = true,继续下一次的for循环,拿到锁,方法返回true,整个的最外层if返回true,执行selfInterupt(),进入临界区
}

这里我解释一下信号值 waitStatus,一共 -3,-2,-1,0,1

/** waitStatus value to indicate thread has cancelled */
// 说明node的线程被取消了
static final int CANCELLED =  1;
/** waitStatus value to indicate successor's thread needs unparking */
// 说明node的线程是被阻塞的
static final int SIGNAL    = -1;
/** waitStatus value to indicate thread is waiting on condition */
// 说明node的线程在等待condition,这个以后再讲
static final int CONDITION = -2;
/**
 * waitStatus value to indicate the next acquireShared should
 * unconditionally propagate
 */
static final int PROPAGATE = -3;
发布了2 篇原创文章 · 获赞 1 · 访问量 59

猜你喜欢

转载自blog.csdn.net/Onstduy/article/details/105275864