持有锁时出现 Java IllegalStateMonitorException

Posted

技术标签:

【中文标题】持有锁时出现 Java IllegalStateMonitorException【英文标题】:Java IllegalStateMonitorException while holding the lock 【发布时间】:2012-01-28 11:06:48 【问题描述】:

我在 java 中编写了一个实现双缓冲区的类。 该类有两个方法写入两个缓冲区和一个清除它们的方法。 然后我有三个线程:一个写入第一个缓冲区,另一个写入第二个缓冲区,第三个清除缓冲区。

在这里,我粘贴(一段)导致问题的代码(我知道它不正确,但出于调试目的我已对其进行了简化):

public void addAlpha(int toAdd)
synchronized (alphaCount) 
    while(alphaCount >= alpha.length)
        try 
        alphaCount.wait();
         catch (InterruptedException e) 
        
    

    alpha[alphaCount] = toAdd;
    alphaCount++;
    

这里是我调用 notifyAll() 的部分:

public void clear()
    synchronized (alphaCount) 
        alphaCount = 0;
        alphaCount.notifyAll();
    

如您所见,在 addAlpha 方法中,我获得了 alphaCount 的锁定,测试条件,然后等待 alphaCount 对象。

在 clear 方法中,我获得了 alphaCount 的锁定,并在其上调用 notifyAll()。 在运行时,我得到 IllegalStateMonitorException...

但我真的不知道错误在哪里:我检查了文档和多个论坛,没有任何运气......

感谢您的时间和关注, 瑞克。

【问题讨论】:

你能发布你的堆栈跟踪吗? 【参考方案1】:

通常,您应该将字段用作锁final,否则您可能会遇到这样的错误。恕我直言,您应该尽可能多地进入决赛。 ;)

synchronized (alphaCount)  // alphaCount == 1 which is locked.
    alphaCount = 0;         // alphaCount == 0 which is not locked.
    alphaCount.notifyAll(); // fails.

此外,我不建议使用 Integer 或 String 或任何包装器类型作为锁。因为有许多令人困惑和令人惊讶的后果。例如

Integer i1 = 127;
Integer i2 = 127; // same object due to the auto-boxing cache.
i1 == i2;

Integer i1 = 128;
Integer i2 = 128; // not the same object.
i1 != i2; // may or may not be the same object depending on the cache size.

另一个问题是,您可能会遇到一个完全不相关的库的死锁,该库也恰好使用整数作为锁。


解决方案是使用专用的锁对象。

private final Object alphaCountLock = new Object();
private int alphaCount = 0; // don't use an object when a primitive will do.

synchronized (alphaCountLock ) 
    alphaCount = 0;
    alphaCountLock .notifyAll();

【讨论】:

感谢您的快速回答。就在几秒钟前,我一直怀疑这个错误是由于我使用的是整数(这是不可变的,我在编写代码时不记得它)。确实,问题出在您在第二段代码中所说的那个。为了解决这个问题,我编写了一个 MyInteger 包装器,现在一切正常。非常感谢你的回复! ^^ +1,很好的答案,我没想到同步变量的内容会改变。 锁定的是引用的对象,而不是字段。 ;) @RiccardoCipolleschi 您可能对 AtomicInteger 感兴趣;) 以及用于在线程之间交换缓冲区的 Exchanger。

以上是关于持有锁时出现 Java IllegalStateMonitorException的主要内容,如果未能解决你的问题,请参考以下文章

为啥锁条件等待必须持有锁

在heroku上部署应用程序时出现过时的纱线锁文件错误

创建互斥锁时出现“找不到路径的一部分”错误

Linux apt下载安装时出现:在等待缓存锁:无法获得锁 /var/lib/dpkg/lock-frontend的问题

Linux apt下载安装时出现:在等待缓存锁:无法获得锁 /var/lib/dpkg/lock-frontend的问题

Linux apt下载安装时出现:在等待缓存锁:无法获得锁 /var/lib/dpkg/lock-frontend的问题