2013-06-02 3 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

Вы знаете, где проблема может быть?

EDIT:

Это метод запуска в станции

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 довольно ясно:

Если текущий поток является удержанием er этой блокировки, то счетчик удержания уменьшается. Если счетчик удержания теперь равен нулю, блокировка освобождается. Если текущая нить не является держателем этого замка, то бросается IllegalMonitorStateException.

Таким образом, резьба, которая пытается разблокировать, не является держателем замка. Мы не можем сказать, почему вы ожидали , чтобы он был тем же, не видя больше вашего кода.

+1

Я добавил два раздела, которые относятся к этому коду. Часть, которая меня смущает, заключается в том, что она фактически должна удерживать замок, поэтому я не знаю, почему .... –

+0

@KelseyAbreu: Оба условия 'if' могут быть' false', и в этом случае ваша нить не владеет замком, поэтому вы не можете его разблокировать. –

+0

Вот почему у меня была if (connected> = 0), где у меня есть глобальная переменная, заданная в -1, если ни один из операторов if не был истинным. Поэтому в методе doWork они будут только разблокированы, если изменится связанное значение. что происходит только в том случае, если любой из операторов if является истинным в методе run. –

8

Я знаю, что этот вопрос больше года, но я столкнулся с одной и той же проблемой, и решение оказалось не другой Thread, которая каким-то образом удерживала 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); 
    } 
    .. 
} 

Если релиз отсчет падает до нуля, exclusiveOwnerThread устанавливается в нуль. И если впоследствии вы попытаетесь освободить блокировку еще раз, вы больше не являетесь exclusiveOwnerThread, так как ваш Thread вряд ли будет null. Так что один простой .unlock() слишком много может привести к этому (в этой ситуации довольно запутанный) Исключение.

Смежные вопросы