2009-10-12 2 views
28

Perché ciò potrebbe accadere? Il fatto è che oggetto monitor non è nullo per certo, ma ancora otteniamo questa eccezione piuttosto spesso:java.lang.IllegalMonitorStateException: (m = null) Impossibile ottenere il monitor per

java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60) 
     at java.lang.Object.wait(Object.java:474) 
     at ... 

Il codice che provoca questa è una soluzione semplice piscina:

public Object takeObject() { 
     Object obj = internalTakeObject(); 
     while (obj == null) { 
      try { 
       available.wait(); 
      } catch (InterruptedException e) { 
       throw new RuntimeException(e); 
      } 
      obj = internalTakeObject(); 
     } 
     return obj; 
    } 

    private Object internalTakeObject() { 
     Object obj = null; 
     synchronized (available) { 
      if (available.size() > 0) { 
       obj = available.keySet().iterator().next(); 
       available.remove(obj); 
       synchronized (taken) { 
        taken.put(obj, Boolean.valueOf(true)); 
       } 
      } 
     } 
     return obj; 
    } 

    public void returnObject(Object obj) { 
     synchronized (taken) { 
      taken.remove(obj); 
     } 
     synchronized (available) { 
      if (available.size() < size) { 
       available.put(obj, Boolean.valueOf(true)); 
       available.notify(); 
      } 
     } 
    } 

Mi manca qualcosa ?

MODIFICA: L'eccezione si verifica nella riga available.wait();.

+0

puoi dirci quale riga è 474 nel codice sorgente? – flybywire

+0

l'eccezione si verifica in available.wait(); linea, ma la linea 474 proviene dalla classe java.lang.Object. –

risposta

53

consultare Javadoc per Object.wait.

in particolare "Il thread corrente deve possedere il monitor di questo oggetto." e "[lancia] IllegalMonitorStateException - se il thread corrente non è il proprietario del monitor dell'oggetto." Cioè, è necessario sincronizzare sull'oggetto che si sta per chiamare attendere.

in modo che il codice dovrebbe essere:

metodo
synchronized (available) { 
    available.wait(); 
} 
+3

Vale la pena sapere: usa lo stesso modello se questa eccezione si verifica su 'available.notify()'. –

+0

Ho provato a utilizzare una funzione sincronizzata anziché un blocco per fare la stessa cosa, ma ha gettato l'IllegalMonitorStateException. Perché? –

+0

Hunter, quando si sincronizza una funzione membro si sta bloccando l'oggetto, quindi 'this.wait()' dovrebbe funzionare. Cosa hai fatto esattamente? – tgdavies

6

available.wait(); devono essere di sezione sincronizzato (disponibile)

0

takeObject() deve essere sincronizzato o, dobbiamo scrivere blocco sincronizzato all'interno di questo metodo. Spero che dovresti ottenere un'eccezione in termini di compilazione per questo.