我要去哪里错了?即使我的使用者线程未持有该锁,该程序也不会针对任何锁调用(解锁/等待/信号)抛出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。
公共无效解锁()
尝试释放此锁。
如果当前线程是此锁的持有者,则保留计数将减少。如果保持计数现在为零,则释放锁定。
If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown
。 最佳答案
该问题似乎基于一些不正确的假设/陈述。
Java ReentrantLock
类没有await
或signal
方法。
这意味着consumers
(很可能)不是ReentrantLock
...,并且代码段中的任何内容都不会调用signal
(或singnal
(sic))。
根据javadoc,ReentrantLock
锁定和解锁方法不会抛出IllegalMonitorStateException
。而且我不希望它们如此,因为lock和unlock方法不能作为原始监视器/互斥体运行。
AFAIK,从Lock
对象中获取该异常的唯一方法是使用原始互斥操作wait
和notify
...,这似乎是对Lock
对象的不正确使用。 (如果要使用这些操作,则任何对象都足够,包括一个普通的Object
实例。)Lock
类旨在提供与Java基本锁正交的锁,并且不限于严格的块结构。它们不直接提供等待和信号。如果需要,您需要创建一个Condition
;例如使用Lock.newCondition()
。注意,如果当前线程不保存IllegalMonitorStateException
...,则Condition.await和signal方法通常将抛出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
时,将引发ANOTHER IllegalMonitorStateException
...,因此看不到第一个。简而言之,这些方法的行为完全符合规范的规定。