J.U.C之AQS:源码解析-超时等待

2019-07-05  本文已影响0人  贪睡的企鹅

AQS如何超时等待

AQS超时等待的本质是让运行的线程能够从阻塞中唤醒并执行完毕。这其中包括2点

独占式超时同步

 /**
 * 功能同acquireInterruptibly,增加等待超时
 */
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
    /** 测试当前线程是否已经中断(如果已经中断会将中断标识重新设置为false)**/
    if (Thread.interrupted())
        /** 抛出异常 **/
        throw new InterruptedException();

    /**
     *子类实现tryAcquire能否获取的独占式同步状态
     *如果返回true则获取同步状态成功方法直接返回
     *如果返回false则获取同步状态失败进入if语句
     */
    return tryAcquire(arg) ||
        doAcquireNanos(arg, nanosTimeout);
}
    
/**
 * 独占获取同步状态,响应中断,同时增加超时机制
 */
private boolean doAcquireNanos(int arg, long nanosTimeout)
        throws InterruptedException {
    if (nanosTimeout <= 0L)
        return false;
    /** 计算超时绝对时间ns **/
    final long deadline = System.nanoTime() + nanosTimeout;
    /** addWaiter创建一个独占式节点node,添加到同步队列尾部.**/
    final Node node = addWaiter(Node.EXCLUSIVE);
    /** 执行是否发生异常 **/
    boolean failed = true;
    try {
        for (;;) {
            /** 1. 获得当前节点的先驱节点  **/
            final Node p = node.predecessor();
            /** 如果当前节点的先驱节点是头结点并且成功获取同步状态 **/
            if (p == head && tryAcquire(arg)) {
                /** 并将当前节点设置为head节点  **/
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return true;
            }
            /** 计算有无超时,如超时则退出 !!!**/
            nanosTimeout = deadline - System.nanoTime();
            if (nanosTimeout <= 0L)
                return false;
            /** 获取锁失败,在shouldParkAfterFailedAcquire中设置节点的等待状态,并线程阻塞(可响应线程被中断),
             * 如果是中断响应设置interrupted = true;
             * 抛出异常,中断导致退出自旋线程不在等待!!
             * 如果阻塞超时被唤醒,进入自旋并判断超时后退出自旋
             * **/
            if (shouldParkAfterFailedAcquire(p, node) &&
                nanosTimeout > spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if (Thread.interrupted())
                throw new InterruptedException();
        }
    } finally {
        /** 发生异常,将当前节点等待状态设置为取消**/
        if (failed)
            cancelAcquire(node);
    }
}
    

共享式超时同步


 /**
 * 功能同acquireSharedInterruptibly,可以响应线程中断
 */
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
        throws InterruptedException {
    /** 测试当前线程是否已经中断(如果已经中断会将中断标识重新设置为false)**/
    if (Thread.interrupted())
        /** 抛出异常 **/
        throw new InterruptedException();
    return tryAcquireShared(arg) >= 0 ||
        doAcquireSharedNanos(arg, nanosTimeout);
}
    
/**
 * 功能同doAcquireSharedInterruptibly,添加超时等待
 */
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
        throws InterruptedException {
    /** 超时时间小于0 直接返回 **/
    if (nanosTimeout <= 0L)
        return false;
    /** 计算超时绝对时间ns **/
    final long deadline = System.nanoTime() + nanosTimeout;
    /** 创建一个共享式节点node,添加到同步队列尾部..**/
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
        for (;;) {
            /** 1. 获得当前节点的先驱节点  **/
            final Node p = node.predecessor();
            /** 如果当前节点的先驱节点是头结点并且成功获取同步状态 **/
            if (p == head) {
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                    /** 将当前节点设置为head,同时只要同步队列中存在等待的节点,
                     * 且节点为共享节点则唤醒head节点后置节点阻塞去竞争同步状态. **/
                    setHeadAndPropagate(node, r);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
            }
            /** 计算有无超时,如超时则退出 !!!**/
            nanosTimeout = deadline - System.nanoTime();
            if (nanosTimeout <= 0L)
                return false;
            /** 获取锁失败,在shouldParkAfterFailedAcquire中设置节点的等待状态,并线程阻塞(可响应线程被中断),
             * 如果是中断响应设置interrupted = true;
             * 抛出异常,中断导致退出自旋线程不在等待!!
             * 如果阻塞超时被唤醒,进入自旋并判断超时后退出自旋
             * **/
            if (shouldParkAfterFailedAcquire(p, node) &&
                nanosTimeout > spinForTimeoutThreshold)
                LockSupport.parkNanos(this, nanosTimeout);
            if (Thread.interrupted())
                throw new InterruptedException();
        }
    } finally {
        /** 发生异常,将当前节点等待状态设置为取消**/
        if (failed)
            cancelAcquire(node);
    }
}
上一篇下一篇

猜你喜欢

热点阅读