IllegalMonitorStateException发生在线程未持有对象锁时调用wait/notify方法,正确做法是在synchronized块中调用并配合while循环检查条件,优先使用java.util.concurrent工具类简化并发控制。

在Java多线程编程中,IllegalMonitorStateException 是一个常见的运行时异常,通常发生在调用 wait()、notify() 或 notifyAll() 方法时线程未持有对象的监视器锁。理解其触发原因并掌握正确的处理方式,是编写稳定并发程序的关键。
理解IllegalMonitorStateException的根本原因
这个异常的核心原因是:线程在没有获取目标对象的内置锁(即synchronized锁)的情况下,尝试调用该对象的 wait()、notify() 或 notifyAll() 方法。
例如以下代码会抛出异常:
new Thread(() -> {someObject.wait(); // 未持有锁,直接抛出IllegalMonitorStateException
}).start();
正确做法是确保这些方法必须在 synchronized 块或方法中被调用:
立即学习“Java免费学习笔记(深入)”;
synchronized (someObject) {someObject.wait(); // 正确:已持有锁
}
使用synchronized确保锁的持有
调用 wait/notify 系列方法前,必须通过 synchronized 获取对象锁。这是最基础也是最重要的预防措施。
- 如果方法需要等待条件,应将整个同步逻辑包裹在 synchronized 块中
- 避免在 synchronized 外部调用 wait,即使之前进入过 synchronized 块也不行,因为锁可能已被释放
- 多个线程操作同一共享资源时,所有涉及 wait/notify 的代码都应使用同一把锁对象
配合while循环使用wait避免虚假唤醒
即使正确持有锁,也应始终在 while 循环中调用 wait(),而不是 if 条件判断。
用 php + mysql 驱动的在线商城系统,我们的目标为中国的中小企业及个人提供最简洁,最安全,最高效的在线商城解决方案,使用了自建的会员积分折扣功能,不同的会员组有不同的折扣,让您的商店吸引更多的后续客户。 系统自动加分处理功能,自动处理会员等级,免去人工处理的工作量,让您的商店运作起来更方便省事 采用了自建的直接模板技术,免去了模板解析时间,提高了代码利用效率 独立开发的购物车系统,使用最
操作系统或JVM可能在没有 notify 的情况下唤醒线程(称为虚假唤醒),因此需要重新检查条件:
synchronized (lock) {while (!conditionMet) {
lock.wait();
}
// 执行条件满足后的操作
}
这样可以确保只有在真正满足条件时才继续执行。
优先考虑高级并发工具替代原始wait/notify
在现代Java开发中,建议使用 java.util.concurrent 包中的工具类来减少手动管理锁和条件的复杂性。
- BlockingQueue:如 ArrayBlockingQueue、LinkedBlockingQueue,适用于生产者-消费者场景
- CountDownLatch:用于等待一组操作完成
- CyclicBarrier:让多个线程互相等待至某一点再继续
- ReentrantLock + Condition:提供比 synchronized 更灵活的等待/通知机制
这些工具内部已正确处理了锁与等待逻辑,能有效避免 IllegalMonitorStateException 的发生。
基本上就这些。关键是理解 wait/notify 必须在 synchronized 上下文中执行,并尽量使用更高层次的并发结构来简化控制流程。不复杂但容易忽略细节。









