如果wait()抛出InterruptedException,那么线程是否会等到获取对象的监视器?

时间:2018-05-02 13:12:52

标签: java multithreading concurrency wait synchronized

例如:

public synchronized Object get() {
    while (result == null) {
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
            // Do we own the monitor of this object?
        }
    }
    return result;
}

e.printStackTrace()执行时,我们是否保证拥有对象的监视器?

该引用表示当wait()notify()调用后notifyAll()返回时,该线程会等待它获取对象的监视器。但是当wait()抛出异常时呢?

2 个答案:

答案 0 :(得分:6)

等待返回时(包括抛出InterruptedException的情况),线程必须有监视器,否则它不能在该synchronized方法中执行。线程必须先获取监视器才能离开wait方法。然后,一旦它离开wait方法,线程就有了监视器,并在线程离开方法时释放它。

这里最好将InterruptedException抛给调用者而不是吃掉它。你的目标是快速离开,让调用者知道发生了中断,这样就可以解决问题。在这里吃它也似乎意味着你再次回到while循环。 java.util.concurrent使用中断来实现取消,特别是如果你使用java.util.concurrent工具,编写与它们兼容的代码是有意义的。

答案 1 :(得分:4)

是。实际上,重新获取监视器后会抛出此InterruptedException

请参阅wait in jls

  

让线程t成为对象m上执行wait方法的线程,并且   设n是m上没有的t的锁定动作的数量   与解锁操作相匹配。发生以下操作之一:

     
      
  • 如果n为零(即,线程t还没有锁定   target m),然后抛出IllegalMonitorStateException。

  •   
  • 如果这是一个定时等待并且nanosecs参数不在范围内   0-999999或毫秒参数是负数,然后是   抛出IllegalArgumentException。

  •   
  • 如果线程t被中断,则抛出InterruptedException   t的中断状态设置为false。

  •   
  • 否则,将发生以下序列:

         
        
    1. 将线程t添加到对象m的等待集中,并执行n unlock   m。

    2. 的行动   
    3. 线程t在执行之前不会执行任何进一步的指令   从m的等待集中删除。可以从等待集中删除该线程   由于以下任何一种行为,并将在某个时间恢复   之后:

           
          
      • 对m执行通知操作,其中选择了t   从等待集中删除。

      •   
      • 正在对m。

      • 执行的notifyAll操作   
      • 正在执行中断操作

      •   
      • 如果这是一次定时等待,则会从m等待中删除内部操作   设置在至少毫秒毫秒加上纳秒之后发生   自等待操作开始以来经过了纳秒。

      •   
      • 实施的内部行动。实施是   允许,尽管不鼓励,进行“虚假的唤醒”,   也就是说,从等待集中删除线程,从而启用恢复   没有明确的指示。

      •   
    4.   
    5. 主题t对m执行n次锁定操作。

    6.   
    7. 如果由于a而在步骤2中从m的等待集中删除了线程t   中断,然后将t的中断状态设置为false并等待   抛出InterruptedException。

    8.   
  •