【Java并发】AQS三:AbstractQueuedSynchronizer同步基础框架内部条件等待ConditionObject

ConditionObject条件实现AQS作为Lock接口实现的基础。
该类的方法文档从锁和条件用户的角度描述了机制,而不是行为规范。该类的导出版本通常需要附带描述依赖于关联的AbstractQueuedSynchronizer的条件语义的文档。

public class ConditionObject implements Condition, java.io.Serializable {
    private static final long serialVersionUID = 1173984872572414699L;
    /* 条件等待头节点 */
    private transient Node firstWaiter;
    /* 条件等待尾节点 */
    private transient Node lastWaiter;

    /* 实例化 */
    public ConditionObject() { }

    // 内部方法

    // 往队列里面添加一个节点
    private Node addConditionWaiter() {
        Node t = lastWaiter;
        // 如果尾节点是取消的,则清除
        if (t != null && t.waitStatus != Node.CONDITION) {
            unlinkCancelledWaiters();
            t = lastWaiter;
        }
        Node node = new Node(Thread.currentThread(), Node.CONDITION);
        if (t == null)
            firstWaiter = node;
        else
            t.nextWaiter = node;
        lastWaiter = node;
        return node;
    }

    /**
     * 删除和传输节点,直到到达不可取消的1或null。从signal中分离出来,部分原因是为了鼓励编译器在没有等待器的情况下内联。
     * @param first (non-null) 条件等待的头结点
     */
    private void doSignal(Node first) {
        do {
            if ( (firstWaiter = first.nextWaiter) == null)
                lastWaiter = null;
            first.nextWaiter = null;
        } while (!transferForSignal(first) &&
                 (first = firstWaiter) != null);
    }

    /**
     * 删除和传输所有节点
     * @param first (non-null) 条件等待的头结点
     */
    private void doSignalAll(Node first) {
        lastWaiter = firstWaiter = null;
        do {
            Node next = first.nextWaiter;
            first.nextWaiter = null;
            transferForSignal(first);
            first = next;
        } while (first != null);
    }

    /**
     *从条件队列中取消已取消的服务员节点的链接。仅在持锁时调用。当在条件等待期间发生取消时调用此函数,当看到
     *lastWaiter已被取消时调用新waiter。在没有信号的情况下,需要使用这种方法来避免垃圾保留。因此,尽管它可能需要一个完整的遍历,
     *但只有在没有信号的情况下超时或取消才会起作用。它遍历所有节点,而不是停在一个特定的目标上,以断开到垃圾节点的所有指针的链接,
     *而不需要在取消风暴期间进行多次重新遍历。
     */
    private void unlinkCancelledWaiters() {
        Node t = firstWaiter;
        Node trail = null;
        while (t != null) {
            Node next = t.nextWaiter;
            if (t.waitStatus != Node.CONDITION) {
                t.nextWaiter = null;
                if (trail == null)
                    firstWaiter = next;
                else
                    trail.nextWaiter = next;
                if (next == null)
                    lastWaiter = trail;
            }
            else
                trail = t;
            t = next;
        }
    }

    // 公共方法

    /**
     * 将等待时间最长的线程(如果存在的话)从该条件的等待队列移动到拥有锁的等待队列。
     * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
     *         returns {@code false}
     */
    public final void signal() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignal(first);
    }

    /**
     * 将此条件下的所有线程从等待队列移动到拥有锁的等待队列。
     * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
     *         returns {@code false}
     */
    public final void signalAll() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        Node first = firstWaiter;
        if (first != null)
            doSignalAll(first);
    }

    /**
     * 实现不可中断条件wait。
     * 保存{@link #getState}返回的锁状态。
     * 使用保存的状态作为参数调用{@link #release},如果失败则抛出IllegalMonitorStateException。
     * 阻塞直到唤醒
     * 通过调用{@link # acquisition}的专门化版本并将保存的状态作为参数重新获取。
     */
    public final void awaitUninterruptibly() {
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean interrupted = false;
        while (!isOnSyncQueue(node)) {
            LockSupport.park(this);
            if (Thread.interrupted())
                interrupted = true;
        }
        if (acquireQueued(node, savedState) || interrupted)
            selfInterrupt();
    }

    /*
     * 对于可中断等待,我们需要跟踪是否抛出InterruptedException(如果在条件阻塞时中断),而不是重新中断当前线程(如果在阻塞等待重新获取时中断)。
     */

    /** 模式意味着在退出等待时重新中断 */
    private static final int REINTERRUPT =  1;
    /** 模式意味着在退出等待时抛出InterruptedException */
    private static final int THROW_IE    = -1;

    /**
     * 模式意味着在waitcheck退出时抛出InterruptedException for interrupt,如果在发出信号之前中断,
     * 返回THROW_IE;如果在发出信号之后重新中断,返回REINTERRUPT;如果没有中断,返回0。
     */
    private int checkInterruptWhileWaiting(Node node) {
        return Thread.interrupted() ?
            (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
            0;
    }

    /**
     * 抛出InterruptedException,重新中断当前线程,或者什么都不做,这取决于模式。
     */
    private void reportInterruptAfterWait(int interruptMode)
        throws InterruptedException {
        if (interruptMode == THROW_IE)
            throw new InterruptedException();
        else if (interruptMode == REINTERRUPT)
            selfInterrupt();
    }

    /**
     * 实现可中断条件wait。
     */
    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;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null) // clean up if cancelled
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
    }

    /**
     * 实现定时条件wait。
     */
    public final long awaitNanos(long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return deadline - System.nanoTime();
    }

    /**
     * 实现绝对定时条件wait。
     */
    public final boolean awaitUntil(Date deadline)
            throws InterruptedException {
        long abstime = deadline.getTime();
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (System.currentTimeMillis() > abstime) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            LockSupport.parkUntil(this, abstime);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

    /**
     * 实现定时条件wait。
     */
    public final boolean await(long time, TimeUnit unit)
            throws InterruptedException {
        long nanosTimeout = unit.toNanos(time);
        if (Thread.interrupted())
            throw new InterruptedException();
        Node node = addConditionWaiter();
        int savedState = fullyRelease(node);
        final long deadline = System.nanoTime() + nanosTimeout;
        boolean timedout = false;
        int interruptMode = 0;
        while (!isOnSyncQueue(node)) {
            if (nanosTimeout <= 0L) {
                timedout = transferAfterCancelledWait(node);
                break;
            }
            if (nanosTimeout >= spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                break;
            nanosTimeout = deadline - System.nanoTime();
        }
        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
            interruptMode = REINTERRUPT;
        if (node.nextWaiter != null)
            unlinkCancelledWaiters();
        if (interruptMode != 0)
            reportInterruptAfterWait(interruptMode);
        return !timedout;
    }

    //  支持工具

    /**
     * 如果该条件是由给定的同步对象创建的,则返回true。
     *
     * @return {@code true} if owned
     */
    final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
        return sync == AbstractQueuedSynchronizer.this;
    }

    /**
     * 查询是否有线程在此条件下等待。实现了{@link AbstractQueuedSynchronizer # hasWaiters (ConditionObject)}。
     */
    protected final boolean hasWaiters() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION)
                return true;
        }
        return false;
    }

    /**
     * 返回在此条件下等待的线程数的估计值。实现了{@link AbstractQueuedSynchronizer # getWaitQueueLength (ConditionObject)}。
     */
    protected final int getWaitQueueLength() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        int n = 0;
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION)
                ++n;
        }
        return n;
    }

    /**
     * 返回包含可能在此条件下等待的线程的集合。
     */
    protected final Collection<Thread> getWaitingThreads() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        ArrayList<Thread> list = new ArrayList<Thread>();
        for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
            if (w.waitStatus == Node.CONDITION) {
                Thread t = w.thread;
                if (t != null)
                    list.add(t);
            }
        }
        return list;
    }
}
大佬们好,做性能压测遇到及其奇怪的问题,机器load极高,甚至飙到100+,逻辑核数只有16核 ![图片说明](https://img-ask.csdn.net/upload/201904/19/1555639361_818159.png) jstack dump的线程有一半的线程都在waiting on condition,而且都是一些tomcat的线程池之类的问题线程栈如下: ![图片说明](https://img-ask.csdn.net/upload/201904/19/1555638646_167074.png) 53%的线程都是如下堆栈 ``` "catalina-exec-7" daemon prio=10 tid=0x00007f52fc016800 nid=0x1430 waiting on condition [0x00007f537abe7000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000073168d480> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Locked ownable synchronizers: - None ``` 附上已确定的可以过滤的影响因素,其中cpu利用率81%,fullgc只有俩次,也不是fullgc问题引起的,parNew gc每次耗时20-40ms之间,也是合理的。内存也足够用 ![图片说明](https://img-ask.csdn.net/upload/201904/19/1555638758_853326.png)
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页