Java 非法监视器状态异常
是什么原因导致我在这段代码中得到非法的MonitorStateExceptionJava 非法监视器状态异常,java,multithreading,notify,illegalmonitorstateexcep,Java,Multithreading,Notify,Illegalmonitorstateexcep,是什么原因导致我在这段代码中得到非法的MonitorStateException synchronized(syncCount){ syncCount--; syncCount.notify(); } 我有点困惑,因为据我所知,运行线程必须在调用通知的对象上有监视器。在我看来,我的代码不可能是错的,但不知何故它是。类型是整数还是类似的--将不可变的整数对象替换为另一个对象。因此,您正在调用notify,调用对象与synchronized不同 您的代码相当于: Integer s
synchronized(syncCount){
syncCount--;
syncCount.notify();
}
我有点困惑,因为据我所知,运行线程必须在调用通知的对象上有监视器。在我看来,我的代码不可能是错的,但不知何故它是。类型是
整数
还是类似的--
将不可变的整数
对象替换为另一个对象。因此,您正在调用notify
,调用对象与synchronized
不同
您的代码相当于:
Integer syncConunt = Integer.valueOf(5);
[...]
synchronized (syncCount) {
syncCount = Integer.valueOf(syncCount.intValue() + 1);
syncCount.notify();
}
你并不孤单。甚至在J2SE5.0之前,我就在一本书中看到过在同步块中指定引用的示例代码。一般来说,最好标记锁定字段final
另一个重要的一点是,代码在它不“拥有”的对象上同步
Integer
对象是共享的(Integer.valueOf(int)
如果使用-128到127之间的值调用,可能会返回完全相同的实例,甚至更远)。如果这是由两段不相关的代码完成的,那么就会有隐藏的交互。这适用于在不相关代码之间共享实例的任何类型。常见的例子有Integer
、String
、Class
(由静态同步方法使用)和Thread
(在Sun的实现中,Thread
恰好被用作join
的锁)。非常感谢。这就解决了问题。它可能会解决抛出的异常,但您应该理解Tom关于声明字段final的说法。在自己的同步块中声明新对象是非常不安全的