欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

理解并比较ReentrantLock的 lockInterruptibly、lock 和 tryLock 功能

最编程 2024-07-28 19:22:29
...

lockInterruptibly

能响应interrupt中断,调用就是会有catch块,catch InterruptedException并处理。

lock

不能响应interrupt中断,interrupt对它没影响,它会继续往下执行程序。

tryLock

尝试获取锁,获取不到直接放弃

tryLock(timeout,timeUnit)

尝试获取锁,在指定时间内拿不到直接放弃

区别::

lock:

可以看到 排队阻塞的方法里头,lock是不会抛出异常的,只是设置interrupted这个变量返回,但这个变量无论true、false,对于获取锁功能没有任何作用, parkAndCheckInterrupt方法里面 ,被唤醒之后执行 Thread.interrupted()返回该线程是否被打断并清除它的中断标志,interrupted 变量是true的话,回到外面执行selfInterrupt()方法,只是还原该线程的中断标志,原因是 不能改变用户对于该线程的 操作,用户想改变它的中断标志,aqs不能擅自改变用户操作。

 public void lock() {
        sync.lock();
    }

final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
lockInterruptibly:(有抛出 InterruptedException )

对于lockInterruptibly,可见是会抛出InterruptedException的,位置在一进来如果判断线程的中断标志是true,立马抛InterruptedException,跳到外面的catch块中。

还有就是在双向队列中排队,被唤醒继续执行,发现线程中断标志是true,立马抛InterruptedException,也是去到catch块中。

public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (!tryAcquire(arg))
            doAcquireInterruptibly(arg);
    }

private void doAcquireInterruptibly(int arg)
        throws InterruptedException {
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
tryLock()

仅仅进行尝试获取锁,直接放回成功还是失败。

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

final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
tryLock(timeout,timeUnit)

还是一开始如果检测到中断标志,直接抛异常不执行下去,如果排队过程超时,放回false,如果排队被唤醒判断是被中断了,直接抛异常。

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

public final boolean tryAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        return tryAcquire(arg) ||
            doAcquireNanos(arg, nanosTimeout);
    }

private boolean doAcquireNanos(int arg, long nanosTimeout)
            throws InterruptedException {
        if (nanosTimeout <= 0L)
            return false;
       //1. 根据超时时间和当前时间计算出截止时间
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (; ; ) {
                final Node p = node.predecessor();
                //2. 当前线程获得锁出队列
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
                // 3.1 重新计算超时时间
                nanosTimeout = deadline - System.nanoTime();
                // 3.2 已经超时返回false
                if (nanosTimeout <= 0L)
                    return false;
                // 3.3 线程阻塞等待
                if (shouldParkAfterFailedAcquire(p, node) &&
                        nanosTimeout > spinForTimeoutThreshold)
                    LockSupport.parkNanos(this, nanosTimeout);
                 // 3.4 线程被中断抛出被中断异常
                if (Thread.interrupted())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

流程图:


推荐阅读