我哪里错了?即使我的消费者线程没有持有锁,程序也不会为任何锁定调用(unlock / await / signal)抛出IllegalMonitorStateException。
更新:
private final ReentrantLock lock = new ReentrantLock();
private final Condition producers = lock.newCondition();
private final Condition consumers = lock.newCondition();
@Override
public void run() {
while (true) {
try {
//lock.lockInterruptibly();
try {
while (sharedResource.isEmpty()) {
printErr(name + " : Queue Empty ..");
consumers.await(500, TimeUnit.MILLISECONDS);
}
String obj = sharedResource.remove(0);
printOut(name + " : " + obj);
if (obj.equals(POISON_PILL)) {
sharedResource.add(POISON_PILL);
// System.err.println(name +" Taking break");
break;
}
producers.signal();
} finally {
lock.unlock();
}
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// if(debug)System.err.println("Consumer Looping");
}
}
void java.util.concurrent.locks.ReentrantLock.unlock()
根据Java Doc。
public void unlock()
尝试释放此锁定。
如果当前线程是此锁的持有者,则保持计数递减。如果保持计数现在为零,则释放锁定。 If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown
。
答案 0 :(得分:2)
该问题似乎是基于一些不正确的假设/陈述。
Java ReentrantLock
类没有await
或signal
方法。
这意味着consumers
(很可能)不是ReentrantLock
...而您的代码段中没有任何内容会调用signal
(或singnal
(sic) ))。
根据javadoc,ReentrantLock
锁定和解锁方法不会抛出IllegalMonitorStateException
。而且我不指望它们,因为锁定和解锁方法不是作为原始监视器/互斥体运行。
AFAIK,从Lock
对象中获取该异常的唯一方法是使用原始互斥操作wait
和notify
...这似乎是一个反常的使用Lock
对象。 (如果要使用这些操作,任何对象就足够了,包括普通的Object
实例。)
Lock
类旨在提供与Java原始锁正交的锁定,而不是严格限制为块结构。它们不提供直接提供等待和信号。如果你想要,你需要创建一个Condition
;例如使用Lock.newCondition()
。请注意,如果当前线程不包含IllegalMonitorStateException
,则Condition.await和信号方法通常将抛出Lock
,但该行为是特定于实现的;请参阅javadoc。
假设consumers
是Condition
,那么有几个原因导致它可能不会抛出异常:
Lock
可能不是由lock
表示的条件。
实际的Lock
类可能会提供不需要锁定的Condition
个对象...
不幸的是,您的代码段缺少一些可以解决这些问题的重要线索。
<强>更新强>
我将您的代码转换为我可以运行的代码:
package test;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Lochy {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition producers = lock.newCondition();
Condition consumers = lock.newCondition();
while (true) {
try {
try {
for (int i = 0; i < 3; i++) {
System.out.println("wait " + i);
consumers.await(500, TimeUnit.MILLISECONDS);
}
producers.signal();
} finally {
lock.unlock();
}
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
当我运行时,我在IllegalMonitorStateException
看到unlock
。
当我在unlock()
发表评论IllegalMonitorStateException
时,我会在await
看到IllegalMonitorStateException
。
事后看来,很清楚它发生了什么。在这两种情况下,await
都会unlock()
抛出finally
,但当您在IllegalMonitorStateException
区块中调用{{1}}时,会引发另一个{{1}} ...所以你不要看不到第一个。
简而言之,这些方法的行为完全符合规范所说的。