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

时间:2015-09-29 10:41:48

标签: java multithreading interrupt

Thread.interrupt()中查询JavaDocs和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();

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

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

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

3 个答案:

答案 0 :(得分:10)

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

原因:

  1. 如果应用程序需要在interrupt()块中调用synchronized,那么规范(javadoc)会这样说,并且还说明需要同步的对象获得线程安全。事实上,javadoc对此一无所知。

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

  3. 如果需要在Thread对象上进行外部同步以使interrupt()调用线程安全,那么很难解释为什么该方法也在进行内部同步。 (如果有必要,他们可以/将会使整个方法同步。)

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

答案 1 :(得分:4)

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

  

为什么需要同步?以及在哪个对象上?

同步的全部要点---唯一的一点是保护数据免受损坏。当一个线程无法提升程序状态而不创建其他线程不允许看到的临时无效状态时,我们使用同步。

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

那么,当我们谈论打断一个线程时,我们在讨论什么状态

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

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

答案 2 :(得分:2)

是的,消息来源称打断死线程无效。所以它本身就是线程安全的。

它说"中断不活动的线程不会产生任何影响。"

  

中断此主题。除非当前线程正在中断   本身,总是被允许的,checkAccess()方法   调用线程,这可能导致抛出SecurityException。   如果在调用wait()时阻塞了这个线程,则等待(long),   或者等待(long,int)Object类或join()的方法,   join(long),join(long,int),sleep(long)或sleep(long,int)方法   这个类,然后它的中断状态将被清除   收到InterruptedException。如果此线程在I / O中被阻止   对java.nio.channels.InterruptibleChannel的操作   中断通道然后通道将被关闭,线程被关闭   将设置interruptstatus,线程将收到一个   java.nio.channels.ClosedByInterruptException。如果这个线程是   在java.nio.channels.Selector中阻塞了线程的中断   状态将被设置,它将立即从选择中返回   操作,可能具有非零值,就像选择器一样   调用了java.nio.channels.Selector唤醒方法。如果没有   先前的条件保持,然后该线程的中断状态将是   组。中断不活动的线程不会产生任何影响。