beimrumprogrammierenmiteinerneuenscriptsprache,dieanvisualbasicangelehntabernochreduzierter/minimaistischer/idiotensichererist, istmirheuteaufgefallen, wielangeichschonnichtmehrforindextoarray.size-1inmeinemcodeschreibenmusste. natürlichhatteichdas-1zunächstvergessen. glücklicherweisnormalerweis ekannichdieweitschlauerenforeach(varentryincollection)inc#, forentryincollectioninpython, oderdoseq[entrycollection]inclojureverwenden. mankannsichdasovielsparen.





{ 10 } Comments
Das mit der foreach-Schleife finde ich auch in Java sehr praktisch. Allerdings bin ich vor wenigen Tage auf ein dieser (für Java neuen) Schleifenform inherentes Problem gestoßen:
Ich verwende(te) diese foreach-Schleife, um eine HashMap elementweise zu durchlaufen und um dabei gleich einige Werte des gerade aktuellen Elementes zu verändern. So weit, so gut. Nun wollte ich allerdings Teile meines Codes aus Effizienzgründen in verschiedenen Threads ausführen lassen – der Code mit der foreach-Schleife findet sich leider auch darin. So erhielt ich sporadische ConcurrentModificationExceptions – übrigens messbar häufiger auf echten Mehrkern-Prozessoren!
Nun könnte man meinen, es sollte ein einfacher synchronized()-Block um das besagte Schleifenkonstrukt helfen – dann sollte keine gleichzeitige Veränderung mehr stattfinden. Dem ist aber nicht so. Das Problem liegt eigentlich nicht in der Verwendung von Threads. Vielmehr ist die Ursache im Zusammenspiel von Hidden Iterator (das foreach-Konstrukt verwendet intern einen Iterator für den elementweisen Durchlauf), Fail Fast Iterator (der implizit verwendete Iterator ist ein solch pessimistischer Iterator) und der von mir verwendeten Datenstruktur HashMap (diese ist nämlich nicht Thread-sicher) zu suchen.
Daher begrüße ich foreach-Schleifen zwar ob ihrer Kompaktheit, vermeide sie aber bei der Verwendung von Threads (in Java).
Wie ist eigentlich die Thread-Sicherheit der foreach-Schleifen bei den von dir erwähnten Programmier- und Skriptsprachen C#, Python und Clojure? Gibt es da auch solche Fallstricke wie in Java?
Hallo Clemens, Um dein Problem besser zu verstehen, erstmal noch eine Frage: ist dein Problem, dass die HashMap noch woanders verwendet wird und durch die Änderungen in der foreach-Schleife eine Exception fliegt, oder fliegt die Exception allein wegen der Änderungen in der Schleife?
Also die Exception fliegt eigentlich wegen der Veränderung der verwendeten HashMap in der foreach-Schleife sobald ich Threads verwende. So zumindest sieht es aufgrund der StackTrace-Ausgabe aus…
Und sobald ein solches Element der ArrayListe verändert oder gelöscht wurde -> bumm
Allerdings – und das will ich hier nochmals betonen – interessanterweise immer nur dann, wenn ich Threads verwendet habe. Verwende ich keine Threads, dann kommt auch keine ConcurrentModificationException mehr – dafür sehen meine generierten Daten “kaputt” aus. Die Suche nach dem Fehler für diese kaputten Daten brachte mich erst auf die nur vermeintlich “tiefe Kopie”…!
Das stimmt aber genau genommen nicht und machte mir die eigentliche Fehlersuche enorm schwierig! Die Fehlerursache lag in einer falsch implementierten clone()-Methode einer ArrayListe, die Teil eines komplexen Objekts ist, das wiederum als Element in oben genannter HashMap erscheint: dort wurde nur die ArrayListe kopiert, nicht aber deren einzelnen Elemente, d.h. die Elemente der “kopierten” ArrayListe referenzierten die selben Objekte
Nochmal eine Nachfrage: Inwiefern wird die HashMap verändert – werden neue Schlüssel/Wert-Paare hinzugefügt, oder werden nur Werte geändert? Die ConcurrentModificationException kann ja auch auftreten, wenn während einer Iteration die iterierte Collection geändert wird – hat also eigentlich erstmal wenig mit der speziellen foreach-Schleife zu tun. Vielleicht kannst du ja einen Codeschnippsel rüberreichen…?
Note to self: die Kommentarfunktionalität (fängt schon bei Textabsätzen an) hier ist sch….lecht und muss überarbeitet werden…
Also Codeschnipsel kann ich dir liefern, aber soll ich dazu erst noch die überarbeitete Kommentarfunktion abwarten? Und wie füge ich den Code am besten ein? Gibt es da sowas wie <code>-Tags?!
Ich werde zusehen, dass ich heute Abend eine bessere Kommentarfunktion habe…
So, es gibt jetzt eine Möglichkeit HTML direkt einzugeben. Das kann auch
<code>-Elemente.Also ich hab hier mal die HTML-Funktionalität ausprobiert … nicht so schön
ich denke, das ist die geschickteste Lösung, oder?
Ich hab stattdessen meinen Account für den Blog gesucht (und gefunden) und werde in den kommenden Tagen einen Eintrag posten…
Wie du willst.
Post a Comment