AQS源码解析(6)acquireInterruptibly

2021-01-08  本文已影响0人  三斤牛肉

reentrantlock中有lockInterruptibly函数,表示可响应中断,之前讲的lock是不会响应中断的:

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt(); //这里会去调用interrupt,但是线程还是会继续执行完
}

lockInterruptibly核心函数:

public final void acquireInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())//如果线程在获取锁之前就被打断,则异常
            throw new InterruptedException();
        if (!tryAcquire(arg))//如果尝试获取锁成功表示没有线程获取锁,不需要排队,则继续执行,就跟new thread一样,改怎么打断就怎么打断
            doAcquireInterruptibly(arg);
    }

doAcquireInterruptibly:

//整段代码和acquireQueued差不多的,唯一的区别在异常
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())//看这里如果parkAndCheckInterrupt返回的是true,表示线程唤醒前曾今被调用Interrupt()过
                    throw new InterruptedException();//则抛出异常,这里就是响应打断,而之前的[acquireQueued](https://www.jianshu.com/p/dcbcea767d69)则会返回parkAndCheckInterrupt的返回值,最终只是保证Interrupt值一致
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
上一篇 下一篇

猜你喜欢

热点阅读