【问题标题】:How does AQS handle interruptsAQS 如何处理中断
【发布时间】:2021-12-27 16:00:44
【问题描述】:

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

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

【问题讨论】:

  • 嗨,欢迎来到 stackoverflow。您能否重新表述您的问题,可能会提供更多上下文信息?我无法理解您到底在问什么。
  • 感谢您的回答。我的问题是,当Thread从block中被唤醒时,使用thread.interrupted()清除中断状态,如果没有获得锁,则Thread再次挂起。按照我的理解应该进入cancelAcquire方法,但是我没有找到入口,你能明白我的意思吗?对不起,我的英语不太好

标签: java java-8 interrupt java.util.concurrent


【解决方案1】:

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

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

当你有一个构造时

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

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

【讨论】:

  • 是的,所以当一个线程被中断时,根据AbstractQueuedSynchronizer的来源,他会再次尝试获取锁,然后继续挂起,所以他无法进入cancelAcquire方法,然后如何取消获取锁?中断的意思是取消锁的获取,但是看源码会继续获取锁,直到成功,然后进入finally方法,不会执行cancelAcquire。这就是我感到困惑的地方。
  • 再次感谢您的回答。我觉得我明白了。对于独占锁,Doug Lea 提供了三种获取方式,“acquireQueued,doAcquireInterruptibly,doAcquireNanos”,其中两种支持中断,我问的方法不支持中断,作者在注释中也说了,“以独占不间断模式获取已在队列中的线程。由条件等待方法和获取使用。”。所以,他不赞成打断。 finally 方法是出于谨慎添加的。但是,cancelAcquire 方法几乎从不进入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 2023-03-18
相关资源
最近更新 更多