IllegalMonitorStateException因未获取锁时调用wait/notify导致,需在synchronized块中调用这些方法,并优先使用ReentrantLock、BlockingQueue等并发工具确保线程安全。
在Java多线程编程中,IllegalMonitorStateException 是一个常见的运行时异常,通常发生在使用 synchronized 方法或代码块之外调用 wait()、notify() 或 notifyAll() 时。这类问题本质是线程同步控制不当导致的监控器(Monitor)状态错误。要正确处理该异常并修复同步问题,关键在于理解其触发机制并实施合理的线程协作策略。
该异常抛出的根本原因是:线程在未获取目标对象的内置锁(即未进入 synchronized 块或方法)的情况下,尝试调用该对象的 wait()、notify() 或 notifyAll() 方法。JVM 要求这些方法必须由持有对象锁的线程执行,否则会抛出 IllegalMonitorStateException。
常见错误示例:
// 错误写法:未加锁直接调用 wait() Object lock = new Object(); lock.wait(); // 抛出 IllegalMonitorStateException
正确的做法是确保调用这些方法前,线程已通过 synchronized 获取对象锁。
为避免此异常并实现安全的线程通信,应遵循以下原则:
正确示例:
synchronized (lock) {
while (!conditionMet) {
lock.wait();
}
// 执行后续操作
}
// 其他线程中
synchronized (lock) {
conditionMet = true;
lock.notifyAll();
}
Java 并发包(java.util.concurrent)提供了更安全、易用的替代方案,可从根本上规避此类问题。
示例:使用 Condition 避免原始 wait/notify 的陷阱
ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); // 等待方 lock.lock(); try { while (!conditionMet) { condition.await(); } } finally { lock.unlock(); } // 通知方 lock.lock(); try { conditionMet = true; condition.signalAll(); } finally { lock.unlock(); }
为减少此类问题的发生,开发过程中应注意:
基本上就这些。只要确保 wait/notify 在 synchronized 上下文中执行,并优先考虑使用 java.util.concurrent 工具类,就能有效避免 IllegalMonitorStateException,提升多线程程序的健壮性。