美文网首页
AbstractQueuedSynchronizer源码分析第二

AbstractQueuedSynchronizer源码分析第二

作者: 永远的太阳0123 | 来源:发表于2019-01-01 00:10 被阅读0次

    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源码分析第二

          本文链接:https://www.haomeiwen.com/subject/knuglqtx.html