# ConcurrentModificationException



## redbomber (16. Okt 2009)

Hi zusammen,
ich habe ein Problem mit einer ConcurrentModificationException und weiss nicht wie ich diese lösen kann?

1. ich glaub zu wissen woher die Exception kommt 

Also in einem Thread wird auf einen großen Datensatz zugegriffen.
Dieser Zugriff wird benötigt um eine Grafische Repräsentation der Daten in einem JPanel zu erstellen.

Nun habe ich das Problem, dass auf diesen Datensatz von unterschiedlichen Stellen her zugegriffen werden kann.
Ein ganz simples Beispiel: Tooltips die mir anzeigen welche Daten sich an einer Position in der grafischen Darstellung befinden. für die Informationen für den Tooltip muss wieder auf den Datensatz zugriffen werden. Wird dabei im Thread noch auf die Daten zugegriffen entsteht die Exception.

Tja...wie kann ich das Problem nur beheben? (Tritt leider nicht nur beim Tooltip auf)


----------



## Illuvatar (16. Okt 2009)

ConcurrentModificationException bedeutet: Du iterierst irgendwo mit einer foreach-Schleife ([c]for(Foo foo : bar)[/c]) über ein Iterable (vermutlich ArrayList oder so). Während der Iteration versucht ein anderer Thread das Iterable zu verändern.
Du könntest z.B: eine normale for-Schleife verwenden um das Problem zu umgehen. Eine andere Möglichkeit wäre, vor der Iteration eine Kopie anzulegen und über die Kopie zu iterieren.
Was in deinem konkreten Fall sinnvoll ist, weiß ich aber nicht - das musst du wissen.


----------



## Landei (16. Okt 2009)

CopyOnWriteArrayList oder so verwenden...


----------



## tfa (16. Okt 2009)

Illuvatar hat gesagt.:


> Während der Iteration versucht ein anderer Thread das Iterable zu verändern.


Oder der selbe Thread.


----------



## Marco13 (16. Okt 2009)

Illuvatar hat gesagt.:


> Du könntest z.B: eine normale for-Schleife verwenden um das Problem zu umgehen.



Da wäre ich mir nicht so sicher ???:L

```
for (int i=0; i<list.size(); i++)
{
    // [COLOR="Red"]Hier ist er noch hingekommen, aber genau JETZT[/COLOR]
    // [COLOR="Red"]leert ein anderer Thread mit list.clear() die list...[/COLOR]
    Object element = list.get(i); // [COLOR="Red"]... und dann kracht's hier...[/COLOR]
}
```
...wenn mich nicht alles täuscht


----------



## Illuvatar (16. Okt 2009)

@tfa: Stimmt. Aber wenn der Fehler nur sporadisch auftritt, vermute ich dass das nicht der Fall ist. Trotzdem möglich - hab ich nicht drangedacht 
@Marco13: Äh... stimmt auch *stellt sich in die Ecke*
Allerdings ist es dann keine ConcurrentModificationException mehr :bae:


----------



## Marco13 (16. Okt 2009)

Man kann die Liste auch vor der Schleife auf [c]list = null;[/c] setzen - dann kommt auch keine ConcurrentModificationException mehr :lol:


----------



## redbomber (16. Okt 2009)

Ja also das Problem tritt dann hierbei auf, also durch den HashIterator.


```
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at java.util.AbstractCollection.addAll(Unknown Source)
at java.util.HashSet.<init>(Unknown Source)
```

Der Datentyp den ich verwende ist nicht von mir, daher kann ich da eigentlich nichts verändern, bzw. die Datenstruktur sollte ziemlich fix bleiben.

Nur noch mal dass ich das richtig verstehe. Der Fehleranfälligkeit liegt also an dem Zugriff durch diesen Iterator?
Für das Erzeugen des Tooltip-Textes verwende ich aber bereits ein:

```
set = Collections.synchronizedSet(new HashSet<Probe>());
```

Sollte dies nicht mein Problem bereits beheben? Ich mein es tuts nich, verstehe aber nicht warum.


----------



## Marco13 (16. Okt 2009)

Damit wird nur sichergestellt, dass sich die "elementaren" Operationen wie get, put, remove usw. nicht in die Quere kommen:

```
public void put(K key, V value)
{
    int hash = key.hashValue();
    int index = hash % tableSize;    
    
    [COLOR="Red"]// Hier macht ein anderer Thread ein "remove", und die table-Größe ändert sich[/COLOR]

    table[index] = value; [COLOR="Red"]// Gibt's eine ArrayIndexOutOfBoundsException[/COLOR]

}
```

Sowas wird durch Collections.synchronized*(..) verhindert.

Mit einem Iterator über so ein Set zu laufen ist aber keine "einzelne, elementare" Operation. Nach jedem "Iterationsschrit" kann jemand anderes das Set verändern.

Die Abhilfe: 

```
set = Collections.synchronizedSet(new HashSet<Probe>());
```
verwenden, wie du es schon machst, und *zusätzlich* and JEDER Stelle, wo über das Set iteriert wird, ein synchronized auf dieses Set

```
synchronized (set) // <-- So synchronized um die Iteration drumrumwickeln
{
    for (Element element : set)
    {
        ..
    }
}
```


----------



## tfa (16. Okt 2009)

Marco13 hat gesagt.:


> und *zusätzlich* and JEDER Stelle, wo über das Set iteriert wird, ein synchronized auf dieses Set


Das ist auch nichts ganz unproblematisch. Es skaliert nicht besonders gut, und man muss jede Stelle erwischen - viele Fehlermöglichkeiten.

Wenn das Set nicht allzu groß wird, oder Manipulationen selten sind, könnte wirklich das schon angesprochene CopyOnWriteArraySet eine Lösung sein.
Bevor ich irgendwo 
	
	
	
	





```
synchronized
```
 dranschreibe, schaue ich lieber im Concurrency-Framework nach, ob es was passendes gibt.


----------

