线程调用非所属锁的wait()抛出IllegalMonitorStateException原因分析
问题原因与解决办法
核心问题所在
你误解了synchronized方法的锁对象和wait()方法的要求:
- 用
synchronized修饰成员方法时,线程进入方法持有的是当前类实例(this)的内置锁,而非参数c对象的锁。 - 调用任意对象的
wait()方法前,必须持有该对象的内置锁。你这里调用c.wait(),但线程并没有获取c的锁,所以必然抛出IllegalMonitorStateException。
两种修正方案
根据你的业务逻辑选择:
基于当前实例的条件等待
如果是要让线程等待当前类实例的状态变化(比如sicherungswunsch或anzahlClients的变化),应该调用当前实例的wait()(即this.wait(),可以省略this直接写wait()):public synchronized void daten_ablegen(Client c) throws InterruptedException { System.out.println("Client " + c.ID + " will Daten ablegen"); while (sicherungswunsch || (anzahlClients >= maxClients)) { System.out.println(c.ID + " sleeps."); wait(); // 等价于this.wait(),当前线程持有this的锁,符合要求 } anzahlClients++; System.out.println(anzahlClients + " Clients legen Daten ab."); }基于Client对象的条件等待
如果确实需要等待c对象的状态变化,需要将同步块的锁对象改为c:public void daten_ablegen(Client c) throws InterruptedException { System.out.println("Client " + c.ID + " will Daten ablegen"); synchronized(c) { while (sicherungswunsch || (anzahlClients >= maxClients)) { System.out.println(c.ID + " sleeps."); c.wait(); // 此时线程持有c的锁,符合要求 } } anzahlClients++; System.out.println(anzahlClients + " Clients legen Daten ab."); }
额外提醒
使用wait()时必须配合while循环检查条件,你当前的写法是正确的——避免线程被虚假唤醒后直接执行后续逻辑。
内容的提问来源于stack exchange,提问作者PaterGauting
相关产品推荐
相关产品推荐

