为什么我收到IllegalMonitorStateException?

当我尝试解锁一个对象时,我得到以下exception。

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; } 

文档很清楚:

如果当前线程是该锁定的持有者,则保持计数减少。 如果保持计数现在为零,则释放锁定。 如果当前线程不是此锁的持有者,则抛出IllegalMonitorStateException

因此,试图解锁的线程不是锁的持有者。 如果没有看到更多代码,我们无法分辨为什么你认为它是同一个线程。

我知道这个问题已经超过一年了,但是我遇到了同样的问题而且解决方案原来并不是另一个以某种方式持有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()过多会导致这种情况(在这种情况下相当混乱)exception。