首页 > 解决方案 > AQS 如何处理中断

问题描述

当一个节点排队等待锁时,另一个线程中断了他,他会旋转一次然后取消中断并重新挂起自己,就像它从未中断过一样。

按照我的理解,他应该取消锁获取,但现在看来不是这样。当他之前的节点释放锁时,他仍然会像从未中断过一样抢锁,谁能告诉我为什么?版本是JDK8

    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);
        }
    }


    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

标签: javajava-8interruptjava.util.concurrent

解决方案


在您的代码中,线程for(;;)只能以一种方式离开该无限循环 - 在它满足条件之后if(p == head && tryAcquire(arg))- 因为它是唯一的return语句,所以您也没有任何中断。

但是,您说“未获得锁定”,这意味着线程必须继续执行此 for 循环中的内容,这意味着执行第二个 if(再次挂起线程)。

当你有一个构造

try {
  // some code
}finally{
 // finally execution
}

块中的代码finally只有在执行离开try块后才会执行(正常或由于异常)。


推荐阅读