Skip to content

offbyone

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

{ 10 } Comments

  1. Clemens Mühlberger | 2011/4/3 at 09:19 | Permalink

    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?

  2. Steffen | 2011/4/5 at 10:30 | Permalink

    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?

  3. Clemens Mühlberger | 2011/4/5 at 01:50 | Permalink

    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…
    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 :-( Und sobald ein solches Element der ArrayListe verändert oder gelöscht wurde -> bumm :-o 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”…!

  4. Steffen | 2011/4/6 at 07:01 | Permalink

    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…?

  5. Steffen | 2011/4/6 at 07:02 | Permalink

    Note to self: die Kommentarfunktionalität (fängt schon bei Textabsätzen an) hier ist sch….lecht und muss überarbeitet werden…

  6. Clemens Mühlberger | 2011/4/6 at 09:15 | Permalink

    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?!

  7. Steffen | 2011/4/6 at 01:51 | Permalink

    Ich werde zusehen, dass ich heute Abend eine bessere Kommentarfunktion habe…

  8. Steffen | 2011/4/6 at 08:14 | Permalink

    So, es gibt jetzt eine Möglichkeit HTML direkt einzugeben. Das kann auch <code>-Elemente.

  9. emerentia | 2011/4/11 at 12:30 | Permalink

    Also ich hab hier mal die HTML-Funktionalität ausprobiert … nicht so schön :-|
    Ich hab stattdessen meinen Account für den Blog gesucht (und gefunden) und werde in den kommenden Tagen einen Eintrag posten… :-) ich denke, das ist die geschickteste Lösung, oder?

  10. Steffen | 2011/4/11 at 08:07 | Permalink

    Wie du willst.

Post a Comment

Your email is never published nor shared. Required fields are marked *