ReentrantLock源码解析之tryLock

ReentrantLock的tryLock方法是对Lock接口的tryLock实现

应用场景

非阻塞的场景,允许某些任务不执行(比如防止重复提交业务),或超时不执行(比如防止资源等待队列溢出)等

不带参数的 tryLock

public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}

实现比较简单,内部调用sync#nonfairTryAcquire方法,该方法前篇分析lock方法的时候已经解析过了在此不做赘述

带超时和支持中断响应的 tryLock

/**
     * Acquires the lock if it is free within the given waiting time and the
     * current thread has not been {@linkplain Thread#interrupt interrupted}.
     *(在指定的时间内获取锁如果锁未被其他线程持有,并且这个线程没有被中断)
     * <p>If the lock is available this method returns immediately
     * with the value {@code true}.
     *(如果锁是可用的这个方法会立刻返回true)
     * If the lock is not available then
     * the current thread becomes disabled for thread scheduling
     * purposes and lies dormant until one of three things happens:
     * (如果锁是不可用的那么当前线程将不可用对于线程调度,并且会休眠直到1件或3件事情发生)
     * <ul>
     * <li>The lock is acquired by the current thread; or
     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
     * current thread, and interruption of lock acquisition is supported; or
     * <li>The specified waiting time elapses
     * </ul>
     *(这个锁被当前线程持有;或者其他的线程中断了当前线程,并且锁的中断是被支持的;或者指定的等待时间超时)
     * <p>If the lock is acquired then the value {@code true} is returned.
     *(如果这个锁被获取那么将返回true)
     * <p>If the current thread:
     * <ul>
     * <li>has its interrupted status set on entry to this method; or
     * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
     * the lock, and interruption of lock acquisition is supported,
     * </ul>
     * then {@link InterruptedException} is thrown and the current thread's
     * interrupted status is cleared.
     * 如果线程被中断将抛出InterruptedException异常
     * <p>If the specified waiting time elapses then the value {@code false}
     * is returned.
     * If the time is
     * less than or equal to zero, the method will not wait at all.
     *(如果指定的等待时间到了还未获取到锁将返回false,如果指定的时间少于或者等于0,方法将不会等待)
     * <p><b>Implementation Considerations</b>
     *(实现的注意事项)
     * <p>The ability to interrupt a lock acquisition in some implementations
     * may not be possible, and if possible may
     * be an expensive operation.
     * The programmer should be aware that this may be the case. An
     * implementation should document when this is the case.
     *(在某些实现中中断锁获取的能力可能不可能,并且可能的话是一个昂贵的操作。程序员应该意识到情况可能是这样的。一个在这种情况下,实现应该记录下来。)
     * <p>An implementation can favor responding to an interrupt over normal
     * method return, or reporting a timeout.
     *(一个实现可以响应一个中断,或者报告超时)
     * <p>A {@code Lock} implementation may be able to detect
     * erroneous use of the lock, such as an invocation that would cause
     * deadlock, and may throw an (unchecked) exception in such circumstances.
     * The circumstances and the exception type must be documented by that
     * {@code Lock} implementation.
     *(实现可能会检测到锁的错误使用,例如可能导致死锁的调用,并可能在这种情况下引发(未经检查的)异常。这种情况和异常类型必须由{@code lock}实现记录)
     * @param time the maximum time to wait for the lock (获取锁的最大等待时间)
     * @param unit the time unit of the {@code time} argument (时间单位)
     * @return {@code true} if the lock was acquired and {@code false}
     *         if the waiting time elapsed before the lock was acquired
     *(如果锁被获取了返回true,如果等待时间超时还未获取则返回false)
     * @throws InterruptedException if the current thread is interrupted
     *         while acquiring the lock (and interruption of lock
     *         acquisition is supported)
     *(当前线程被中断了需要返回InterruptedException当获取锁的时候(并且锁的获取中断是被支持的))
     */
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

查看ReentrantLock的实现

public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}

sync#tryAcquireNanos 调用的是父类AbstractQueuedSynchronizer的tryAcquireNanos方法

    /**
     * Attempts to acquire in exclusive mode, aborting if interrupted,
     * and failing if the given timeout elapses.  Implemented by first
     * checking interrupt status, then invoking at least once {@link
     * #tryAcquire}, returning on success.  Otherwise, the thread is
     * queued, possibly repeatedly blocking and unblocking, invoking
     * {@link #tryAcquire} until success or the thread is interrupted
     * or the timeout elapses.  This method can be used to implement
     * method {@link Lock#tryLock(long, TimeUnit)}.
     *
     * @param arg the acquire argument.  This value is conveyed to
     *        {@link #tryAcquire} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @param nanosTimeout the maximum number of nanoseconds to wait
     * @return {@code true} if acquired; {@code false} if timed out
     * @throws InterruptedException if the current thread is interrupted
     */
    public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        //中断检测
        if (Thread.interrupted())
            throw new InterruptedException();
        //step1. 调用tryAcquire先尝试获取锁,如果失败则调用doAcquireNanos
        return tryAcquire(arg) ||
            doAcquireNanos(arg, nanosTimeout);
    }

AbstractQueuedSynchronizer#doAcquireNanos

    /**
     * Acquires in exclusive timed mode.
     *
     * @param arg the acquire argument
     * @param nanosTimeout max wait time
     * @return {@code true} if acquired
     */
    private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
        //计算出到期时间
        final long deadline = System.nanoTime() + nanosTimeout;
        //新增独占节点
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            //反复重试直到成功获取锁或者超时返回false
            for (;;) {
                final Node p = node.predecessor();
                //该节点的前节点是头节点则尝试获取锁
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
                //剩余时间
                nanosTimeout = deadline - System.nanoTime();
                if (nanosTimeout <= 0L)
                    //超时返回false
                    return false;
                //shouldParkAfterFailedAcquire 判断是否需要阻塞线程 并且剩余时间大于 spinForTimeoutThreshold (默认1000)
                if (shouldParkAfterFailedAcquire(p, node) &&
                    nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                    
                //中断检测
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

猜你喜欢

转载自www.cnblogs.com/lomoye/p/12699238.html