是否需要同步对中断方法的调用?

2022-09-02 10:38:48

查阅JavaDocs和方法的源代码,我发现这个:Thread.interrupt()Java SE 7

public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();

    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0(); //1, Outside of the synchronized block
}

//...

private native void interrupt0();

可以看出,at 的本机方法调用位于同步块之外。那么,如果不将对方法的调用放入块中,是否安全?//1interrupt()synchronized

Thread t;
//something else
t.interrupt(); //Not in a synchronized block

它会是线程安全的吗?如果超过1个线程将尝试同时中断它怎么办?那么,本机方法将如何表现呢?interrupt0


答案 1

我会说是的...它是线程安全的。

原因:

  1. 如果应用程序需要调用一个块,那么规范(javadoc)会这样说,并且还会说你需要同步哪个对象来获得线程安全。事实上,javadoc对此只字未提。interrupt()synchronized

  2. 如果应用程序需要调用一个块,那么Oracle Java并发教程将在此页面上提到它。事实并非如此。interrupt()synchronized

  3. 如果为了使调用线程安全,必须对对象进行外部同步,则很难解释为什么该方法也执行内部同步。(如果有必要,他们可以/会让整个方法同步。Threadinterrupt()

上述证据是令人信服的,尽管不是绝对的证据。如果您想要线程安全的证明,可以通过对 的本机代码实现进行彻底分析来获得。我还没有看过本机代码,但我希望它是内部线程安全的,并且足以使方法线程安全。interrupt()interrupt0()interrupt0interrupt


答案 2

@xehpuk的问题值得更多关注:

为什么它需要同步?在哪个物体上?

整个同步点---唯一的一点---是保护数据免受损坏。当一个线程无法在不创建临时无效状态的情况下推进程序状态时,我们使用同步。该状态一定不允许其他线程查看。

在这种情况下,我们将同步创建临时无效状态的代码块,并且还必须同步每个查看该状态的代码块。

那么,当我们谈论中断线程时,我们在谈论什么状态

好吧,不看代码,似乎只有两个:未中断中断,它们都是有效的。从一个状态到另一个状态没有明显的无效状态:从未中断状态到中断状态似乎是一个原子操作。因此,一个理性的程序员会期望不需要同步。

当然,可能有一些内部细节我跳过了,但内部细节应该对程序员隐藏。一个理性的程序员会期望,如果需要同步,那么它要么在方法内部处理,要么会非常清楚地记录为调用者的责任。interrupt()