Java Thread-Sicherheit: Wird hier eine Synchronisierung benötigt? (theoretisch)

Mit großer Wahrscheinlichkeit weil plötzlich ein Resize auftritt. Und das bisher keiner aufgetreten ist, wird unter anderem mit der Initialgröße einer HashMap zu tun haben, was ein optionales Konstruktor-Argument ist, aber man nicht als garantierten Wert über alle JVMs und Standardlibraries betrachten sollte.
 
  • Gefällt mir
Reaktionen: CyborgBeta
CyborgBeta schrieb:
Danke. Jetzt ist bei mir auch gerade der Fehler aufgetreten:
Tjo ;)
Hashmap ist in Java eine ziemlich miese Klasse, weil sie versucht unterschiedliche Implementierungen "ideal" zu nutzen, von einem simplen array, zu einer TreeMap und wahrscheinlich noch mehr.
Sobald du den Übergang zwischen den Implementierungen erwischt muss es krachen :)
 
  • Gefällt mir
Reaktionen: CyborgBeta
Klar, denn nun sind die Zugriffe nicht mehr disjunkt, denn n Threads greifen auf einen Key zu.. bei 64 Threads pro Thread einen eigenen Key würde vermutlich wiederum klappen...
Ich frage mich ob wir hier nicht ein xy Problem haben...
 
  • Gefällt mir
Reaktionen: mental.dIseASe
:D Na ja, wenigstens kam es nun zu einem (schönen) null value ... theoretisch wäre auch ein ungültiger int value möglich gewesen (da die Schreiboperation ja nicht "atomar" sein muss), aber das hab ich bislang noch nirgendwo auf einem Computer gesehen.

Edit: Und ein ungültiger int-Wert wäre dann nicht sofort durch eine NPE aufgefallen ...
 
  • Gefällt mir
Reaktionen: CyborgBeta
Tornhoof schrieb:
Hashmap ist in Java eine ziemlich miese Klasse, weil sie versucht unterschiedliche Implementierungen "ideal" zu nutzen, von einem simplen array, zu einer TreeMap und wahrscheinlich noch mehr.
HashMap ist schon die Implementierung. Map wäre das allgemeine. TreeMap ist eine Map, keine HashMap.

Und das wurde hier nicht vermischt.
CyborgBeta schrieb:
(da die Schreiboperation ja nicht "atomar" sein muss)
Java / JVM machen hier keine Garantien. Hängt an der Zielplatform ob es ist oder nicht. Damit auf einem normalen DesktopPC sehr unwahrscheinlich dass das Schreiben eines alignten Pointers/Handles nicht atomar ist.

Und dein viel-Thread Biespiel wird kaputt gehen, weil du die Keys zum ersten Mal parallel hinzufügst und nicht bevor die Threads anfangen. Wenn du alle Keys einmal anlegsts und danach nur noch das Mapping änderst, umschiffst du das die Metadaten der HashMap sich ändern müssen. Aber das ist natürlich deshalb absolut nicht zu empfehlen, weil es hochgradig fragil ist und nicht leicht dem Code anzusehen. Und du missbrauchst hier Wissen über die exakten Internas der HashMap, was man auch nicht garantieren kann.
 
  • Gefällt mir
Reaktionen: CyborgBeta
Ray519 schrieb:
HashMap ist schon die Implementierung. Map wäre das allgemeine. TreeMap ist eine Map, keine HashMap.
Jein:
Code:
* This map usually acts as a binned (bucketed) hash table, but
     * when bins get too large, they are transformed into bins of
     * TreeNodes, each structured similarly to those in
     * java.util.TreeMap. Most methods try to use normal bins, but
     * relay to TreeNode methods when applicable (simply by checking
     * instanceof a node).  Bins of TreeNodes may be traversed and
     * used like any others, but additionally support faster lookup
     * when overpopulated. However, since the vast majority of bins in
     * normal use are not overpopulated, checking for existence of
     * tree bins may be delayed in the course of table methods.

Schau dir den Quelltext an ;)
 
  • Gefällt mir
Reaktionen: CyborgBeta
KeepCalm schrieb:
Ich frage mich ob wir hier nicht ein xy Problem haben...
Eigentlich habe ich noch über den Code nachgedacht, den ich in diesem Thema geschrieben hatte: https://www.computerbase.de/forum/threads/java-e-mails-lesen.2204679/

Dort gibt es nur zwei E-Mail-Accounts ... Aber es wäre ja auch möglich, die Liste auf 10 oder 100 E-Mail-Accounts zu erweitern, und falls dann zufällig zwei oder mehrere Accounts zum fast gleichen Zeitpunkt abgerufen werden würden, gäbe es auch dort ein Problem.

Sprich, auch die dort eingesetzte Map sollte entweder durch Synchronisierung geschützt werden oder speziell concurrent sein.

Aber ein XY-Problem ist das eigentlich noch nicht. ;)
 
Tornhoof schrieb:
Schau dir den Quelltext an ;)
Ja. Du hast recht, es mischt auch andere Aspekte mit rein. Auch wenn es keine TreeMap im Sinne von Java ist, weil die ist auch eine SortedMap.

Spannend dass ich das gar nicht auf dem Schirm hatte. War die ganze Zeit am überlegen, womit ich das verwechsle? War das von Anfang an so? Oder verwechsle ich das wirklich mit der kotlin/common Implementierung, weil ich mir die zuletzt angesehen habe?
 
Ray519 schrieb:
War das von Anfang an so?
Du hast hier einen guten Überblick: https://akcoding.com/java-tutorial/java-collections-framework/#historical-background

tl;dr: Das war afaik seit 1.2 so. Später kamen dann noch Generics/Autoboxing (1.5) und Concurrent (since ?) hinzu: https://medium.com/@chandantechie/c...y-features-and-upcoming-releases-54be35646cca

Da Java strikt abwärtskompatibel ist, wird sich auch an der Kern-Implementation kaum etwas geändert haben.

In den Java-Docs verrät dir auch das "Since:", seit wann es eine Klasse, etc. erstmals gab.

tl;dr 2: In der Praxis braucht man meist nur HashMap (unsortiert), LinkedHashMap (merkt sich die Einfüge-Reihenfolge) oder TreeMap (immer sortiert). Jede Map-Implementierung hat die Eigenschaften, dass die Schlüssel einzigartig sind und ggf. null als Schlüssel erlaubt ist.

Jede Map-Implementierung hat für die einzelnen Operationen (ctor, insert, update, delete, find, resize/scale usw.) unterschiedliche Laufzeit-Schranken, überwiegend aber O(1) oder O(log n).

So, das war nun ein kurzer Abriss.^^
 
Zurück
Oben