PDA

View Full Version : [Java] Problema concorrenza


-Slash
07-05-2012, 21:18
Salve ragazzi :D

Ho un problema su cui sto sbattendo la testa da stamattina e non riesco a venirne a capo :muro:

Ho una serie di thread, ognuno dei quali gestisce un TreeSet di un particolare oggetto da me creato. Tale TreeSet è allocato nella run() del runnable con una new. Questo albero è riempito a partire da un albero dato in ingresso al costruttore del runnable. Chiamo poi una funzione che elabora questo albero e che funziona perfettamente in un ambiente non multithreading.

Il codice più o meno è cosi (in realtà la stessa operazione è fatta più volte in un ciclo while):


public class MyRunnable implements Runnable
{
TreeSet<MyClass> in;
public MyRunnable(TreeSet<MyClass> in)
{
this.in = in
}
public void run()
{
TreeSet<MyClass> mytree= new TreeSet<MyClass>();

mytree.addAll(in);
...
ClasseStatica.myFunction(mytree);



}
}

In teoria, da quello che so, l'albero che ho allocato dovrebbe essere esclusivo per ogni thread. Tuttavia la maggior parte delle volte l'esecuzione va a buon fine, mentre altre volte la funzione myFunction non fa quello che dovrebbe fare . Il tutto si risolve completamente se dichiaro myFunction (funzione statica) come synchronized, ma in questo modo il codice sarebbe molto meno parallelo...

Non capisco perchè devo mettere synchronized visto che il TreeSet dovrebbe essere esclusivo di ogni thread... Invece debuggando un po' accade come se un altro thread accedesse a quell'albero e togliesse un nodo :(

Dove sbaglio?

Mettiu_
08-05-2012, 00:02
Ciao, guardando la javadoc relativa al metodo addAll() si legge:
public boolean addAll(Collection c);
Adds all of the elements in the specified collection to this set.
Non dice da nessuna parte che il metodo esegue una COPIA degli elementi ma solo degli handle, motivo per cui tutti i threads si trovano a maneggiare gli stessi oggetti e si danno fastidio a vicenda.
Sto assumendo che allochi gli oggetti della classe MyRunnable passando al costruttore sempre lo stesso oggetto, da qui il problema sopra detto. Devi risolvere la concorrenza in qualche modo. Nel package java.util.concurrent ci sono varie classi per implementare strutture dati concorrenti.

U-Boat
08-05-2012, 12:34
- ClasseStatica.myFunction(Treeset) è rientrante (http://it.wikipedia.org/wiki/Codice_rientrante)? In altre parole, non va a modificare nulla di condiviso e lavora solo su variabili locali alla funzione stessa?

- gli oggetti di MyClass come sono? Sono immutabili? Sono thread-safe?