java 为什么我会收到 IllegalMonitorStateException?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16884061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why am I getting IllegalMonitorStateException?
提问by Kelsey Abreu
I get the following Exception being thrown when I try to unlock an object.
当我尝试解锁一个对象时,我收到以下异常。
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)
All that Pipe.unlock is doing is the following:
Pipe.unlock 所做的一切如下:
public void unlock(){
accessLock.unlock();
}
Where accessLock is an ReentrantLock
其中 accessLock 是 ReentrantLock
Do you know where the issue could be?
你知道问题出在哪里吗?
EDIT:
编辑:
This is the run method in Station
这是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();
While this is the doWork method:
虽然这是 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;
}
回答by xor_eq
I know this question is more than a year old, but I was facing the same problem and the solution turned out to be not another Thread that was holding the Lock somehow but basically a very simple mistake and the inner details of a ReentrantLock. If we look at the implementation of tryRelease:
我知道这个问题已经有一年多了,但我遇到了同样的问题,结果证明不是另一个以某种方式持有锁的线程,而是一个非常简单的错误和 ReentrantLock 的内部细节。如果我们看一下 tryRelease 的实现:
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
..
if (c == 0) {
..
setExclusiveOwnerThread(null);
}
..
}
If the release-count drops to zero, the exclusiveOwnerThread is set to null. And if you afterwards try to release the lock once more, you're not the exclusiveOwnerThread anymore, since your Thread is unlikely to be null. So one simple .unlock() too much can lead to this (in this situation rather confusing) Exception.
如果发布计数降为零,则exclusiveOwnerThread 设置为空。如果您之后再次尝试释放锁,您就不再是exclusiveOwnerThread,因为您的Thread 不太可能为空。所以一个简单的 .unlock() 太多会导致这个(在这种情况下相当混乱)异常。
回答by Jon Skeet
The documentationis pretty clear:
该文档是相当清楚的:
If the current thread is the holder of this lock then the hold count is decremented. If the hold count is now zero then the lock is released. If the current thread is not the holder of this lock then
IllegalMonitorStateException
is thrown.
如果当前线程是此锁的持有者,则持有计数递减。如果保持计数现在为零,则释放锁。如果当前线程不是此锁的持有者,
IllegalMonitorStateException
则抛出。
So the thread which is trying to unlock isn't the holder of the lock. We can't tell why you expectedit to be the same thread without seeing more of your code.
所以试图解锁的线程不是锁的持有者。如果没有看到更多代码,我们无法说出为什么您希望它是同一个线程。