当我尝试解锁对象时,我会抛出以下异常。
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.unlock(Unknown Source)
at Pipe.unlock(Pipe.java:21)
at Station.doWork(Station.java:81)
at Station.run(Station.java:66)
at java.lang.Thread.run(Unknown Source)
Pipe.unlock所做的就是以下内容:
public void unlock(){
accessLock.unlock();
}
其中accessLock是ReentrantLock
你知道问题出在哪里吗?
编辑:
这是Station中的run方法
if(Pipes[inConnection].accessLock.tryLock()){
System.out.println("Station "+ StationNumber+": granted access to pipe "+inConnection+".");
//This is just a way for me to keep track if both pipes have been granted
if(connected<0)
connected=inConnection;
else
connected+=inConnection;
}
if(Pipes[outConnection].accessLock.tryLock()){
System.out.println("Station "+ StationNumber+": granted access to pipe "+outConnection+".");
//This is just a way for me to keep track if both pipes have been granted
if(connected<0)
connected=outConnection;
else
connected+=outConnection;
}
doWork();
虽然这是doWork方法:
private void doWork() {
if(connected==inConnection+outConnection){
System.out.println("Station "+StationNumber+": successfully flows "+inConnection+".");
System.out.println("Station "+StationNumber+": successfully flows "+outConnection+".");
Pipes[inConnection].unlock();
System.out.println("Station "+StationNumber+": released access to pipe "+inConnection+".");
Pipes[outConnection].unlock();
System.out.println("Station "+StationNumber+": released access to pipe "+outConnection+".");
try {
Thread.sleep(rand.nextInt(200));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
WorkLoad--;
}else if(connected >=0 ){
Pipes[connected].unlock();
System.out.println("Station "+StationNumber+": released access to pipe "+connected);
}
connected=-1;
}
答案 0 :(得分:10)
我知道这个问题已经超过一年了,但我遇到了同样的问题,解决方案原来并不是另一个以某种方式持有Lock的线程,但基本上是一个非常简单的错误和ReentrantLock的内部细节。如果我们看一下tryRelease的实现:
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
..
if (c == 0) {
..
setExclusiveOwnerThread(null);
}
..
}
如果release-count降为零,则将exclusiveOwnerThread设置为null。如果你之后尝试再次释放锁,那么你不再是exclusiveOwnerThread了,因为你的Thread不太可能是null。所以一个简单的.unlock()太多会导致这种情况(在这种情况下相当混乱)异常。
答案 1 :(得分:6)
documentation非常明确:
如果当前线程是此锁的持有者,则保持计数递减。如果保持计数现在为零,则释放锁定。如果当前线程不是此锁的持有者,则抛出
IllegalMonitorStateException
。
所以试图解锁的线程不是锁的持有者。我们无法告诉你为什么期望它是同一个线程而没有看到更多的代码。