wait()调用时出现IllegalMonitorStateException

pra*_*ani 156 java multithreading wait

我在我的程序中使用java中的多线程.我已成功运行线程,但在我使用时Thread.wait(),它正在抛出java.lang.IllegalMonitorStateException.我怎样才能使线程等到通知为止?

rec*_*les 167

你需要在一个synchronized街区才能Object.wait()工作.

另外,我建议查看并发包而不是旧的学校线程包.它们更安全,更易于使用.

快乐的编码.

编辑

我认为你的意思Object.wait()是你的例外是当你试图获得访问权而没有持有对象锁时会发生什么.

  • 您正在等待的对象上的同步块。希望编辑此答案以使其更加清楚吗?谢谢。 (2认同)

Tom*_*ine 52

wait定义在Object,而不是它Thread.监视器Thread有点不可预测.

虽然所有Java对象都有监视器,但通常最好有一个专用锁:

private final Object lock = new Object();
Run Code Online (Sandbox Code Playgroud)

通过使用命名类,您可以以较小的内存成本(每个进程大约2K)轻松读取诊断信息:

private static final class Lock { }
private final Object lock = new Lock();
Run Code Online (Sandbox Code Playgroud)

为了waitnotify/ notifyAll对象,您需要使用synchronized语句持有锁.此外,您将需要一个while循环来检查唤醒条件(在线程上找到一个好文本来解释原因).

synchronized (lock) {
    while (!isWakeupNeeded()) {
        lock.wait();
    }
}
Run Code Online (Sandbox Code Playgroud)

通知:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}
Run Code Online (Sandbox Code Playgroud)

在进入多线程时,了解Java语言和java.util.concurrent.locks锁(和java.util.concurrent.atomic)是非常值得的.但是java.util.concurrent尽可能使用数据结构.

  • @ Brent212对于除"wait"以外的任何方法,是的,你永远不会得到`notify`.但是,在`Object.wait`的API文档中,"线程释放了此监视器的所有权".因此,在`wait`中,就好像它在封闭的`synchronized`块之外(对于同一个对象,可能是同一个对象上的多个`synchronized`块). (6认同)
  • 鉴于wait和notify都在同一个对象(锁定)上的同步块中,我永远不会理解这是如何工作的.由于等待线程在块中,不应该使"同步(锁定)"行上的通知线程块? (5认同)

小智 24

我知道这个帖子差不多2年了,但仍然需要关闭它,因为我也遇到了同样问题的Q/A会话......

请一遍又一遍地阅读illegalMonitorException的这个定义......

抛出IllegalMonitorException以指示线程已尝试在对象的监视器上等待,或者在没有指定监视器的情况下通知在对象监视器上等待的其他线程.

这一行一次又一次地说,当出现2种情况之一时,IllegalMonitorException就会出现....

1>在没有指定监视器的情况下等待对象的监视器.

2>通知在对象监视器上等待的其他线程,而不拥有指定的监视器.

有些人可能得到了他们的答案......谁都没有,那么请检查2个陈述....

同步(对象)

的Object.wait()

如果两个对象都相同...则不会发生illegalMonitorException.

现在再次阅读IllegalMonitorException定义,你不会再忘记它了...


Ste*_*n C 5

根据您的评论,听起来您正在做这样的事情:

Thread thread = new Thread(new Runnable(){
    public void run() { // do stuff }});

thread.start();
...
thread.wait();
Run Code Online (Sandbox Code Playgroud)

有三个问题.

  1. 正如其他人所说,obj.wait()只有在当前线程持有原始锁/互斥锁时才能调用obj.如果当前线程没有锁定,则会看到您看到的异常.

  2. 这个thread.wait()电话没有做你似乎期待它做的事情.具体来说,thread.wait() 不会导致指定的线程等待.而是它导致当前线程等到其他线程调用thread.notify()thread.notifyAll().

    实际上没有安全的方法来强制Thread实例暂停,如果它不想要.(Java对此最近的是不推荐使用的Thread.suspend()方法,但该方法本质上是不安全的,如Javadoc中所述.)

    如果您希望新开始Thread暂停,最好的方法是创建一个CountdownLatch实例并await()在锁存器上调用线程来暂停.然后主线程将调用countDown()锁存器以使暂停的线程继续.

  3. 与前面的点正交,使用Thread对象作为锁/互斥锁可能会导致问题.例如,javadoc Thread::join表示:

    此实现使用一系列this.wait调用条件this.isAlive.当一个线程终止时,该this.notifyAll方法被调用.建议应用程序无法使用wait,notifynotifyAllThread实例.