2010-01-12 15 views
13

Che cosa può causare che ottengo IllegalMonitorStateException in questo codiceIllegalMonitorStateException

synchronized(syncCount){ 
    syncCount--; 
    syncCount.notify(); 
} 

Sono po 'confuso, dal momento che, per quanto ne so in esecuzione filo deve avere il monitor su un oggetto che è comunicare è chiamato. Mi sembra che il mio codice non possa essere sbagliato, ma in qualche modo lo è.

risposta

23

Di tipo Integer o simile? -- sostituisce l'immutabile oggetto Integer con un altro. Pertanto chiami notify su un oggetto diverso da synchronized.

Il codice è l'equivalente di:

Integer syncConunt = Integer.valueOf(5); 
[...] 
synchronized (syncCount) { 
    syncCount = Integer.valueOf(syncCount.intValue() + 1); 
    syncCount.notify(); 
} 

Non siete soli. Anche prima di J2SE 5.0, ho visto un codice di esempio pubblicato in un libro che assegnava un riferimento all'interno di un blocco sincronizzato. In generale, è consigliabile contrassegnare i campi di blocco final.

Un altro punto significativo è che il codice si sincronizza su un oggetto che non "possiede". Gli oggetti Integer sono condivisi (Integer.valueOf(int) restituiranno esattamente la stessa istanza se chiamati con valori compresi tra -128 e 127 e forse anche oltre). Se questo fosse fatto da due pezzi di codice non correlato, allora ci sarebbero interazioni nascoste. Questo vale per qualsiasi tipo in cui le istanze sono condivise tra codice non correlato. Esempi comuni sono Integer, String, Class (utilizzato dai metodi statici sincronizzati) e Thread (nell'implementazione di Sun, Thread si utilizza come blocco per join).

+1

Grazie mille. Questo risolve il problema. –

+0

Può risolvere l'eccezione lanciata ma dovresti capire cosa sta dicendo Tom riguardo alla dichiarazione del campo finale. È molto pericoloso dichiarare un nuovo oggetto nel proprio blocco sincronizzato –

+1

bug di concorrenza. –