2013-06-02 44 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()太多可能導致這種情況(在這種情況下相當混亂)異常。

相關問題