使用类.class作synchronized监视器抛IllegalMonitorStateException的原因
异常触发的核心原因
Java 对 wait()、notify()、notifyAll() 三个方法的调用有强制约束:
- 三个方法是所有Java对象从
Object类继承的实例方法,必须由当前线程已经成功获取到锁的那个监视器对象本身调用,否则就会抛出IllegalMonitorStateException。 - 正常运行的版本中,synchronized块锁定的是
this(当前WaitTest实例),代码内直接写的notify()、wait()本质是隐式调用this.notify()、this.wait(),调用对象和持有的锁完全匹配,因此逻辑可以正常跑通。 - 触发异常的版本中,synchronized块把监视器换成了
WaitTest.class(类加载阶段生成的Class对象),当前线程持有的是这个Class对象的锁,但代码里的notify()、wait()仍然在隐式调用当前实例this的对应方法——相当于持有A对象的锁,却去操作B对象的等待唤醒逻辑,完全违反调用规则,自然触发异常。
修正方案
两种符合规则的改法任选其一即可:
- 如果要保留
WaitTest.class作为锁:把synchronized块内所有的notify()替换为WaitTest.class.notify(),所有的wait()替换为WaitTest.class.wait(),保证调用方法的对象和持有的锁对象完全对齐。 - 如果不想修改现有方法调用:直接把synchronized块的监视器换回
this,和可正常运行的原有逻辑保持一致。
踩坑提示:很多初学者会误以为
wait()是Thread类的静态方法,实际上它是和对象锁强绑定的实例方法,脱离锁的持有权限调用这三个方法,必然会抛出非法监视器状态异常。
内容的提问来源于stack exchange,提问作者andrewlawrence
相关产品推荐
相关产品推荐

