2013-06-02 46 views
0

当我尝试解锁对象时,出现以下异常。我为什么会收到IllegalMonitorStateException?

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的

你知道哪里的问题可能是什么?

编辑:

这是车站的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

我觉得这是更好地发布完整的代码/ SSCCE – pinkpanther

回答

6

documentation是相当清楚的:

如果当前线程是保留呃这个锁,然后保持计数递减。如果保持计数现在为零,则锁定被释放。如果当前线程不是该锁的持有者,则引发IllegalMonitorStateException

因此,试图解锁的线程不是锁的持有者。我们不能说明为什么你预计它是相同的线程没有看到更多的代码。

+1

我添加了涉及到的代码中的两个部分。 让我困惑的部分是它实际上应该锁定锁定,所以我不知道为什么...... –

+0

@ KelseyAbreu:你的两个if条件可能都是false,在这种情况下,你的线程不拥有锁 - 所以你不能解锁它。 –

+0

这就是为什么我有if(连接> = 0),其中我有一个全局变量设置为-1,只要这两个if语句都没有为真。因此,在doWork方法中,只有在连接值发生变化时才会解锁。这只有在run方法中的任何if语句为真时才会发生。 –

8

我知道这个问题已经超过一年了,但我面临同样的问题,并且解决方案竟然不是另一个拿着锁定的线程,但基本上是一个非常简单的错误和一个内部细节ReentrantLock的。如果我们看一下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。如果你之后试图再次释放锁,那么你不再是唯一的使用者线程,因为你的线程不可能为空。所以一个简单的.unlock()太多可能导致这种情况(在这种情况下相当混乱)异常。

相关问题