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

fhu*_*cho 9 java concurrency multithreading synchronized wait

例如:

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

e.printStackTrace()执行,是我们保证自己的对象的显示器呢?

引用说当wait()在一个notify()或者notifyAll()调用之后返回时,线程会等待它获取对象的监视器.但wait()抛出异常时的情况呢?

Nat*_*hes 6

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

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


孙兴斌*_*孙兴斌 5

是的。事实上,这InterruptedException是在重新获取监视器后抛出的。

请参阅jls 中的等待

令线程 t 为对对象 m 执行 wait 方法的线程,令 n 为 t 对 m 的锁定操作(尚未与解锁操作匹配)的数量。发生以下操作之一:

  • 如果 n 为零(即,线程 t 尚未拥有目标 m 的锁),则抛出 IllegalMonitorStateException。

  • 如果这是定时等待并且 nanosecs 参数不在 0-999999 范围内或者 millisecs 参数为负数,则抛出 IllegalArgumentException。

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

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

    1. 线程t被添加到对象m的等待集中,并对m执行n次解锁操作。

    2. 线程 t 在从 m 的等待集中删除之前不会执行任何进一步的指令。由于以下任一操作,线程可能会从等待集中删除,并将在稍后恢复:

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

      • 正在 m 上执行的 notificationAll 操作。

      • 正在 t 上执行中断操作

      • 如果这是定时等待,则自该等待操作开始以来至少经过 millisecs 毫秒加上 nanosecs 纳秒后发生从 m 的等待集中删除 t 的内部操作。

      • 实施的内部行动。尽管不鼓励,但允许实现执行“虚假唤醒”,即从等待集中删除线程,从而在没有明确指令的情况下启用恢复。

    3. 线程 t 对 m 执行 n 次锁定操作。

    4. 如果线程 t 在步骤 2 中因中断而从 m 的等待集中移除,则 t 的中断状态将设置为 false,并且 wait 方法将抛出 InterruptedException。