Newsgroup: it.comp.java
Titolo: Thread e ConcurrentModificationException

Allora è tutta la sera che sto cercando di risolvere questo bug... ma senza risultati
Ho un thread che scorre una lista (TreeSet) con un iterator. Sull'help c'è scritto
che non è sincronizzata e devo pensarci io. Solo che non  ho ben capito:
dice che se c'è un'oggetto wrapper che la incapsula posso sincronizzare quell'oggetto, altrimenti
devo usare la sintassi
protected SortedSet OPEN =  Collections.synchronizedSortedSet(new TreeSet());
ed io ho fatto così...
però dopo dice anche che in questo modo mi assicuro solo che venga generata un'eccezione e non che
non ci siano problemi (ed in effetti ci sono tali e quali). Ora il fatto strano è che nmel mio
programma
ci sono 3 thread ma soltanto uno usa la lista OPEN e quindi come può accadere un problema di
concorrenza?
Ne ho pensate 1000 ma non ne vengo a capo.
Sotto riporto una specie di simil-codice :
il mio prog fa una ricerca A*, quindi la classe Ricerca mantiene una lista dei nodi
dell'albero di ricerca. Ad ogni passo della ricerca estraggo il nodo in testa a OPEN e
genero i successori. Se il successore è OK lo metto in OPEN altrimenti passo al successivo.
Ora io carico da file una configurazione iniziale e faccio partire la ricerca: ma a un
certo punto (sempre lo stesso, nodo = 28352) viene lanciata
l'eccezione ConcurrentModificationException
Le classi sono all'incirca queste:
class Stato {
  private int x,y; // stato del robot posizione xy
}
class Nodo {  // nodo nell'albero di ricerca
 Stato stato;
 int nID; // id del nodo incrementato sempre
}
class Ricerca {
 protected TreeSet OPEN  // nodi dell'albero di ricerca da controllare
 protected HashMap CLOSED // nodi già estratti dalla testa di OPEN e controllati
  ...
}
class RicercaAlgoritmo extends Ricerca implements Runnable {
// metodo che controlla se un nodo successore appena generato non sia già presente in OPEN
private boolean nodoPresenteInOPEN(Nodo n2) {
        boolean trovato = false;
        synchronized (OPEN_SYNCH) {
            try {
                Iterator it = OPEN.iterator();
                while (it.hasNext()) {
                    Nodo nodoInOpen = (Nodo) (it.next());    <<------ Exception
                    Stato statoInOpen = nodoInOpen.getStato();
                    if (statoInOpen.equals(statoFrontiera)) {
   ......
   ......
                        }
                    }
                }
            }
            catch (ConcurrentModificationException cex) {
                System.out.println(""+cex.getMessage());
            }
        }
        return trovato;
    }
}
ho aggiunto quell'OPEN_SYNCH (classe) con qualche speranza ... ma dovrei SAPERE quali altri
thread accedono ad OPEN per poter mettere anche nel loro codice il pezzo
synchronized (OPEN_SYNCH) {
} !!!
... ma a me sembra che gli altri miei thread non facciano nulla di male
cioè ad OPEN non ci accedono direttamente (e poi è protected)
nè tantomeno devono modificarla...
semmai al massimo devono leggerla per far vedere sullo schermo quanti nodi sono stati processati
attualemtne, ma anche questa cosa l'ho tolta per essere più sicuro.
ho fatto il debug che parte quando viene
catturata l'eccezione
catch (ConcurrentModificationException cex) {
     cex.printStackTrace();
}
sembrerebbe che gli altri "miei" thread siano in Sleep(100)
cosa assurda: l'id del nodo che è processato quando viene catturata l'eccezione è
sempre lo stesso: 28352 !!!
come mai?
idee su come fare a trovare il codice incriminato?
PS: per inciso il controllo su OPEN è molto costoso, viene fatto per ogni nodo
successore e devo scorrere tutta la lista OPEN. Siccome la lista OPEN può composta da 10000 nodi e i
nodi successori sono nell'ordine dei 100.000 ho circa 10^9 accessi ad OPEN !!!
scusate la lunghezza ma non riesco a essere conciso e centrare il punto ;-)

Nella documentazione di ConcurrentModificationException
puoi leggere:
  Note that this exception does not always indicate that an object
  has been concurrently modified by a different thread. If a single
  thread issues a sequence of method invocations that violates the
  contract of an object, the object may throw this exception.
  For example, if a thread modifies a collection directly while
  it is iterating over the collection with a fail-fast iterator,
  the iterator will thow this exception.
- Dario
Inviato da 
www.mynewsgate.net

 - Dario
č vero!!... grazie non l'avrei mai trovato
il problena č che mi dava l'errore sull'iterator e alcune righe piů
giů facevo l'inserimento mentre io pensavo SOLO di leggere i valori!!!
(ed č in effetti giustissimo perchč se mentre itero aggiungo un
valore l'iterat potrebbe anche incazz...)