我需要同步对中断方法的调用吗?

Do I need to synchronize a call to the interrupt method?

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

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

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

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

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

是的,消息来源说中断死线程没有任何效果。所以它本质上是线程安全的。

它说 "Interrupting a thread that is not alive need not have any effect."

Interrupts this thread. Unless the current thread is interrupting itself, which is always permitted, the checkAccess() methodof this thread is invoked, which may cause a SecurityException to be thrown. If this thread is blocked in an invocation of the wait(), wait(long), or wait(long,int) methods of the Object class, or of the join(), join(long), join(long,int), sleep(long), or sleep(long,int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException. If this thread is blocked in an I/O operation upon an java.nio.channels.InterruptibleChannel interruptiblechannel then the channel will be closed, the thread's interruptstatus will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException. If this thread is blocked in a java.nio.channels.Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's java.nio.channels.Selector wakeup method were invoked. If none of the previous conditions hold then this thread's interrupt status will be set. Interrupting a thread that is not alive need not have any effect.

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

原因:

  1. 如果应用程序有必要在 synchronized 块中调用 interrupt(),那么规范(javadoc)会这样说,还会说明您的对象需要同步以获得线程安全。事实上,javadoc 对此只字不提。

  2. 如果应用程序需要在 synchronized 块中调用 interrupt(),那么 Oracle Java 并发教程会提到它 on this page.它没有。

  3. 如果 Thread 对象上的外部同步对于使 interrupt() 调用线程安全是必要的,那么很难解释为什么该方法进行内部同步出色地。 (如果有必要,他们可以/本来可以使整个方法同步。)

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

@xehpuk 的问题更值得关注:

Why would it need synchronization? And on which object?

同步的全部要点——唯一的要点——是保护数据免于损坏。当一个线程不可能在不创建不允许其他线程看到的临时无效状态的情况下推进程序状态时,我们使用同步。

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

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

嗯,不看代码,好像只有两个:不中断interrupted,两者都有效。从一个状态到另一个状态没有明显的无效状态:从不中断状态变为中断状态 似乎是 一个原子操作。因此,合理的程序员会期望不需要同步。

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