6

当我尝试解锁对象时抛出以下异常。

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 是一个可重入锁

你知道问题可能出在哪里吗?

编辑:

这是 Station 中的运行方法

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

2 回答 2

13

我知道这个问题已有一年多的历史了,但是我遇到了同样的问题,结果证明不是另一个以某种方式持有锁的线程,而是基本上一个非常简单的错误和可重入锁的内部细节。如果我们看一下 tryRelease 的实现:

protected final boolean tryRelease(int releases) {
  int c = getState() - releases;
  if (Thread.currentThread() != getExclusiveOwnerThread())
     throw new IllegalMonitorStateException();
  ..
  if (c == 0) {
    ..
    setExclusiveOwnerThread(null);
  }
  ..
}

如果释放计数降至零,则将 ExclusiveOwnerThread 设置为 null。如果你之后再次尝试释放锁,你就不再是 ExclusiveOwnerThread,因为你的 Thread 不太可能为空。所以一个简单的 .unlock() 太多会导致这个(在这种情况下相当混乱)异常。

于 2014-08-29T15:12:18.597 回答
9

文档很清楚:

如果当前线程是这个锁的持有者,那么持有计数就会递减。如果保持计数现在为零,则释放锁。如果当前线程不是这个锁的持有者,那么IllegalMonitorStateException就会被抛出。

所以试图解锁的线程不是锁的持有者。如果没有看到更多代码,我们无法说出您为什么期望它是同一个线程。

于 2013-06-02T15:11:50.097 回答