You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线程调用非所属锁的wait()抛出IllegalMonitorStateException原因分析

问题原因与解决办法

核心问题所在

你误解了synchronized方法的锁对象和wait()方法的要求:

  • 用synchronized修饰成员方法时,线程进入方法持有的是当前类实例(this)的内置锁,而非参数c对象的锁。
  • 调用任意对象的wait()方法前,必须持有该对象的内置锁。你这里调用c.wait(),但线程并没有获取c的锁,所以必然抛出IllegalMonitorStateException。

两种修正方案

根据你的业务逻辑选择:

  1. 基于当前实例的条件等待
    如果是要让线程等待当前类实例的状态变化(比如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.");
    }
    
  2. 基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 21:35:37