我已经在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 ...
但是我真的不知道错误在哪里:我检查了文档并查看了多个论坛,但没有任何运气...
感谢您的时间和关注,
瑞克
最佳答案
通常,应将字段用作锁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();
}