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

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

 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会如何表现?

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

原因:

  1. 如果应用程序需要在synchronized块中调用interrupt() ,则规范(javadoc)会这样说,并且还说明需要同步的对象以获得线程安全性。 事实上,javadoc对此没有任何说明。

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

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

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

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

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

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

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

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

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

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

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

它说“中断一个没有活着的线程不会产生任何影响。”

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