AbstractQueuedSynchronizer源码分析第二部分——Condition

1 Condition接口

public interface Condition {
    void await() throws InterruptedException;
    void awaitUninterruptibly();
    long awaitNanos(long nanosTimeout) throws InterruptedException;
    boolean await(long time, TimeUnit unit) throws InterruptedException;
    boolean awaitUntil(Date deadline) throws InterruptedException;
    void signal();
    void signalAll();
}

2 AbstractQueuedSynchronizer.ConditionObject内部类

AbstractQueuedSynchronizer.ConditionObject实现了Condition接口。
一个Condition对象对应一个条件队列。

2.1 AbstractQueuedSynchronizer.ConditionObject中的字段

(1)firstWaiter:条件队列的头节点。
(2)lastWaiter:条件队列的尾节点。

        private transient Node firstWaiter;
        private transient Node lastWaiter;

2.2 AbstractQueuedSynchronizer.ConditionObject中的常量

(1)REINTERRUPT:当前节点中的线程对象退出等待时,恢复中断状态。
(2)THROW_IE:当前节点中的线程对象退出等待时,抛出异常。

        private static final int REINTERRUPT =  1;
        private static final int THROW_IE    = -1;

3 AbstractQueuedSynchronizer.ConditionObject中的await方法

        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);
                // 运行到这里,存在三种情况
                // (1)其它线程调用了signal方法或signalAll方法,signal方法调用了doSignal方法,signalAll方法调用了doSignalAll方法,doSignal方法或doSignalAll方法调用了LockSupport中的unpark方法
                // (2)其它线程调用了signal方法或signalAll方法,signal方法调用了doSignal方法,signalAll方法调用了doSignalAll方法,doSignal方法或doSignalAll方法没有调用LockSupport中的unpark方法;之后其它线程调用了unparkSuccessor方法,unparkSuccessor方法中调用了LockSupport中的unpark方法
                // (3)其它线程调用了当前线程的interrupt方法
                // 如果其它线程调用了当前线程的interrupt方法,跳出循环
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            // 运行到这里,说明已经将当前线程所在节点移出条件队列并插入到同步队列中
            // 当前线程获取独占锁
            // 如果acquireQueued方法返回false,interruptMode不变
            // 如果acquireQueued方法返回true并且interruptMode等于-1,interruptMode不变
            // 如果acquireQueued方法返回true并且interruptMode不等于-1,将interruptMode设为1
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            // 在上方调用了checkInterruptWhileWaiting方法,checkInterruptWhileWaiting方法中可能调用transferAfterCancelledWait方法
            // transferAfterCancelledWait方法中可能将当前线程所在节点中的waitStatus设为0,并将当前线程所在节点插入到同步队列中,不会将当前线程所在节点中的nextWaiter字段设为null
            if (node.nextWaiter != null)
                // 移出条件队列中所有waitStatus不等于-2的节点
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                // 恢复中断状态或抛出异常
                reportInterruptAfterWait(interruptMode);
        }

3.1 AbstractQueuedSynchronizer.ConditionObject中的addConditionWaiter方法

调用addConditionWaiter方法时,当前线程已经获取独占锁,在条件队列中进行的操作是线程安全的。

        // 为当前线程创建节点,并将这个节点插入到条件队列中
        private Node addConditionWaiter() {
            Node t = lastWaiter;
            // 如果条件队列的尾节点不等于null并且条件队列的尾节点中的waitStatus不等于-2
            if (t != null && t.waitStatus != Node.CONDITION) {
                // 移出条件队列中所有waitStatus不等于-2的节点
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            // 为当前线程创建节点,并将这个节点插入到条件队列中
            Node node = new Node(Thread.currentThread(), Node.CONDITION);
            if (t == null)
                firstWaiter = node;
            else
                t.nextWaiter = node;
            lastWaiter = node;
            return node;
        }
3.1.1 AbstractQueuedSynchronizer.ConditionObject中的unlinkCancelledWaiters方法
        // 移出条件队列中所有waitStatus不等于-2的节点
        private void unlinkCancelledWaiters() {
            // t代表当前正在检查哪个节点
            Node t = firstWaiter;
            // trail代表哪个节点中的nextWaiter字段等于t节点
            Node trail = null;
            while (t != null) {
                Node next = t.nextWaiter;
                // 如果t节点中的waitStatus不等于-2
                if (t.waitStatus != Node.CONDITION) {
                    t.nextWaiter = null;
                    // 如果trail节点等于null,说明t节点是条件队列的头节点
                    if (trail == null)
                        firstWaiter = next;
                    // 如果trail节点不等于null,说明t节点不是条件队列的头节点
                    else
                        trail.nextWaiter = next;
                    // 如果t节点中的nextWaiter字段等于null,将条件队列的尾节点设为trail节点
                    if (next == null)
                        lastWaiter = trail;
                }
                else
                    trail = t;
                // 继续循环,检查t节点中的nextWaiter字段
                t = next;
            }
        }

3.2 AbstractQueuedSynchronizer.ConditionObject中的fullyRelease方法

    // 释放独占锁
    // 传入的node节点是当前线程所在节点
    final int fullyRelease(Node node) {
        // failed等于true代表当前线程尚未释放独占锁
        // failed等于false代表当前线程已经释放独占锁
        boolean failed = true;
        try {
            int savedState = getState();
            if (release(savedState)) {
                failed = false;
                return savedState;
            } else {
                throw new IllegalMonitorStateException();
            }
        } finally {
            // 如果抛出IllegalMonitorStateException,将当前线程所在节点中的waitStatus设为1
            if (failed)
                node.waitStatus = Node.CANCELLED;
        }
    }

3.3 AbstractQueuedSynchronizer.ConditionObject中的isOnSyncQueue方法

    // 判断是否已经将当前线程所在节点移出条件队列并插入到同步队列中
    // 传入的node节点是当前线程所在节点
    final boolean isOnSyncQueue(Node node) {
        // 如果当前线程所在节点中的waitStatus等于-2或当前线程所在节点中的prev字段等于null,返回false
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        // 如果当前线程所在节点中的next字段不等于null,返回true
        if (node.next != null)
            return true;
        // 运行到这里,说明当前线程所在节点中的waitStatus不等于-2、prev字段不等于null、next字段等于null
        // 判断同步队列中是否存在当前线程所在节点
        return findNodeFromTail(node);
    }
3.3.1 AbstractQueuedSynchronizer中的findNodeFromTail方法
    // findNodeFromTail方法只有可能被isOnSyncQueue方法调用
    // 判断同步队列中是否存在当前线程所在节点
    // 传入的node节点是当前线程所在节点
    private boolean findNodeFromTail(Node node) {
        Node t = tail;
        for (;;) {
            if (t == node)
                return true;
            if (t == null)
                return false;
            t = t.prev;
        }
    }

3.4 AbstractQueuedSynchronizer.ConditionObject中的checkInterruptWhileWaiting方法

        private int checkInterruptWhileWaiting(Node node) {
            return Thread.interrupted() ?
                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                0;
        }
3.4.1 AbstractQueuedSynchronizer中的transferAfterCancelledWait方法
    // 传入的node节点是当前线程所在节点
    final boolean transferAfterCancelledWait(Node node) {
        // 尝试将当前线程所在节点中的waitStatus设为0
        // 这里的CAS操作同样在transferForSignal方法中出现,transferForSignal方法被doSignal方法和doSignalAll方法调用,doSignal方法被signal方法调用,doSignalAll方法被signalAll方法调用
        // 如果CAS操作成功,说明transferForSignal方法没有进行CAS操作
        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
            // 将当前线程所在节点插入到同步队列中
            enq(node);
            return true;
        }
        // 运行到这里,说明CAS操作失败,transferForSignal方法已经进行CAS操作
        // transferForSignal方法成功进行CAS操作之后会调用enq方法,将当前线程所在节点插入到同步队列中
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

3.5 AbstractQueuedSynchronizer.ConditionObject中的reportInterruptAfterWait方法

        private void reportInterruptAfterWait(int interruptMode)
            throws InterruptedException {
            // 抛出异常
            if (interruptMode == THROW_IE)
                throw new InterruptedException();
            // 恢复中断状态
            else if (interruptMode == REINTERRUPT)
                selfInterrupt();
        }

4 AbstractQueuedSynchronizer.ConditionObject中的signal方法

        public final void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            // 如果条件队列的头节点不等于null
            if (first != null)
                doSignal(first);
        }

4.1 AbstractQueuedSynchronizer.ConditionObject中的doSignal方法

        private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }

我们可以将doSignal方法改写成另一种形式。

        // 传入的first节点是条件队列的头节点,传入的first节点不等于null
        private void doSignal(Node first) {
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            // 将条件队列中原来的头节点中的nextWaiter字段设为null
            first.nextWaiter = null;
            while (!transferForSignal(first) && (first = firstWaiter) != null) {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                // 将条件队列中原来的头节点中的nextWaiter字段设为null
                first.nextWaiter = null;
            }
        }
4.1.1 AbstractQueuedSynchronizer.ConditionObject中的transferForSignal方法
    final boolean transferForSignal(Node node) {
        // 尝试将node节点中的waitStatus设为0
        // 这里的CAS操作同样在transferAfterCancelledWait方法中出现
        // 如果CAS操作失败,说明transferAfterCancelledWait方法已经进行CAS操作
        // transferAfterCancelledWait方法成功进行CAS操作之后会调用enq方法,将node节点插入到同步队列中
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
            return false;
        // 运行到这里,说明CAS操作成功,transferAfterCancelledWait方法没有进行CAS操作
        // 将node节点插入到同步队列中,p代表node节点中的prev字段
        Node p = enq(node);
        int ws = p.waitStatus;
        // 如果p节点中的waitStatus等于1,唤醒node节点中的线程对象
        // 如果p节点中的waitStatus不等于1,尝试将p节点中的waitStatus设为-1;如果CAS操作失败,唤醒node节点中的线程对象
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);
        return true;
    }

你可能感兴趣的:(AbstractQueuedSynchronizer源码分析第二部分——Condition)