根本原因是当前线程没有持有该对象的监视器锁,必须在synchronized块或方法中调用wait()、notify()、notifyall(),且锁对象与调用对象必须一致,否则抛illegalmonitorstateexception。

调用 wait() 或 notify() 抛出 IllegalMonitorStateException,根本原因是当前线程**没有持有该对象的监视器锁**(即没在 synchronized 代码块或方法中调用它们)。
必须在 synchronized 块或 synchronized 方法中调用
Java 规定:只有已经获得对象锁的线程,才能调用该对象的 wait()、notify()、notifyAll()。否则 JVM 直接抛出异常。
- 错误写法(会抛异常):
obj.wait(); // 没加 synchronized,非法
- 正确写法(必须同步后调用):
synchronized (obj) {
obj.wait();
}
同理,notify() 和 notifyAll() 也必须出现在同一对象的 synchronized 块内。
确保 wait/notify 使用的是同一个锁对象
常见误区:在不同对象上加锁,却在另一个对象上调用 wait/notify。
- 错误示例:
synchronized (lock1) {
lock2.wait(); // 锁的是 lock1,等的是 lock2 → 异常
}
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 正确做法:wait/notify 的调用对象,必须与 synchronized 锁的对象一致:
synchronized (obj) {
obj.wait(); // ✅ 锁 obj,等 obj
obj.notify(); // ✅ 锁 obj,唤醒 obj 上等待的线程
}
避免在静态方法中混用实例锁和类锁
静态 synchronized 方法锁的是 Class 对象;普通 synchronized 方法或块锁的是实例对象。二者不互通。
- 错误示例:
synchronized static void method() {
this.wait(); // this 是实例,但锁的是 Class → 异常
}
- 解决方案:
– 若需操作实例状态,改用实例方法 + 实例锁;
– 若需跨实例协调,统一使用 MyClass.class 作为锁对象,并在其上 wait/notify:
synchronized (MyClass.class) {
MyClass.class.wait();
}
注意 wait() 的唤醒方式和条件检查
虽然不直接导致 IllegalMonitorStateException,但常伴随使用错误:
-
wait()可能被虚假唤醒(spurious wakeup),必须配合 while 循环检查条件; -
wait()返回后自动重新获取锁,但业务逻辑可能已过期,需二次校验; - 不要用 if 判断条件后 wait —— 应该用 while:
synchronized (obj) {
while (!conditionMet) {
obj.wait();
}
// 处理逻辑
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










