AbstractQueuedSynchronizer ConditionObject解析

分析过程

// condition队列第一个节点
private transient Node firstWaiter;
// condition队列最后一个节点
private transient Node lastWaiter;
// 重新中断退出等待
private static final int REINTERRUPT =  1;
// 抛出中断异常退出等待
private static final int THROW_IE    = -1;

首先来看 ConditionObject. await() 等待方法

// AbstractQueuedSynchronizer.ConditionObject
public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    // 【为等待队列添加新节点】
    Node node = addConditionWaiter();
    //【为当前状态值调用释放方法,返回保存状态,在失败时取消节点并抛出异常】
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    // 【判断等待队列上的节点是否正在同步队列上等待获取锁】
    while (!isOnSyncQueue(node)) {
        LockSupport.park(this); // 阻塞线程
    // 等待后检查中断
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
            break;
    }
    // 使用独占不可中断模式获取锁 且 中断模式不是THROW_IE 则设置中断模式为REINTERRUPT
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
        interruptMode = REINTERRUPT;
    if (node.nextWaiter != null) // clean up if cancelled
        unlinkCancelledWaiters(); //【断开condition队列已取消的等待节点】
    if (interruptMode != 0)
        reportInterruptAfterWait(interruptMode); // 根据中断模式进行相应处理
}

为等待队列添加新节点

// AbstractQueuedSynchronizer.ConditionObject
private Node addConditionWaiter() {
    Node t = lastWaiter;
    // 如果最后一个等待是取消状态则移除
    if (t != null && t.waitStatus != Node.CONDITION) {
        unlinkCancelledWaiters(); // 【断开取消状态的等待结点】
        t = lastWaiter;
    }
    // 创建状态为CONDITION的新节点
    Node node = new Node(Thread.currentThread(), Node.CONDITION);
    if (t == null)
        firstWaiter = node; // condition队列为空,添加为第一个节点
    else
        t.nextWaiter = node; // 将原有最后一个等待结点的前一个节点指向当前节点
    lastWaiter = node; // 将当前节点设置为condition队列的最后一个节点
    return node;
}

断开取消状态的等待结点

private void unlinkCancelledWaiters() {
    Node t = firstWaiter; // 第一个等待节点
    Node trail = null; // 存储状态为CONDITION的遗留节点
    // 从头开始循环condition队列
    while (t != null) {
        Node next = t.nextWaiter;
        // 如果等待状态为CONDITION 则将下一个节点设置为null,断开关联
        if (t.waitStatus != Node.CONDITION) {
            t.nextWaiter = null;
            // 如果没有遗留节点,则将下一个节点设置为第一个节点
            if (trail == null)
                firstWaiter = next;
            else
                trail.nextWaiter = next; // 存在遗留节点,将下一个节点设置为遗留节点的下一个节点
        // 遍历至尾部,将condition队列最后一个节点指向遗留节点
        if (next == null)
                lastWaiter = trail; 
        }
        else
            trail = t; // 记录状态为CONDITION的遗留节点
        t = next; // 循环下一个节点
    }
}

为当前状态值调用释放方法,返回保存状态,在失败时取消节点并抛出异常

final int fullyRelease(Node node) {
    boolean failed = true;
    try {
        int savedState = getState(); // 获取同步状态
        // 释放锁
        if (release(savedState)) {
            failed = false;
            return savedState;
        } else {
            throw new IllegalMonitorStateException();
        }
    } finally {
        // 释放失败将节点状态设置为取消
        if (failed)
            node.waitStatus = Node.CANCELLED; 
    }
}

判断等待队列上的节点是否正在同步队列上等待获取锁

final boolean isOnSyncQueue(Node node) {
    // 如果节点等待状态为CONDITION 或 节点的前驱节点为空,则返回false
    if (node.waitStatus == Node.CONDITION || node.prev == null)
        return false;
    // 节点存在后继节点,说明还在同步队列上等待获取锁
    if (node.next != null) // If has successor, it must be on queue
        return true;
    return findNodeFromTail(node); // 从队列尾部开始查找当前节点是否处于同步队列中
}

ConditionObject.signal() 唤醒方法

// AbstractQueuedSynchronizer.ConditionObject
public final void signal() {
    // 判断是否处于独占状态
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignal(first); // 【执行唤醒操作】
}

执行唤醒操作

private void doSignal(Node first) {
    do {
        // 将头节点设置为头节点的下一个节点并判断是否为空
        if ( (firstWaiter = first.nextWaiter) == null)
            lastWaiter = null; // 如果为空则将最后一个节点设置为空
        first.nextWaiter = null; // 将头节点的下一节点设置为空
    } while (!transferForSignal(first) &&
             (first = firstWaiter) != null);
}

转换条件队列节点至同步队列

final boolean transferForSignal(Node node) {
    // CAS设置等待状态,设置失败说明节点已经被取消
    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
        return false;

    Node p = enq(node); // 将节点添加至同步队列
    int ws = p.waitStatus;
    // 如果节点被取消 或 CAS设置等待状态为SIGNAL失败
    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
        LockSupport.unpark(node.thread); // 唤醒节点所属线程
    return true;
}

主要的等待唤醒方法分析完成。

参考资料

并发编程的艺术

猜你喜欢

转载自blog.csdn.net/laravelshao/article/details/82899183