Ich folge einem Tutorial und es erklärt im Grunde die Ursache der Race-Bedingung, die passiert, wenn man Hashmap in einer Multithread-Umgebung skaliert:
Wenn in Java zwei Threads gleichzeitig festgestellt wurden, dass HashMap jetzt die Größe ändern muss, versuchen beide, die Größe zu ändern. Bei der Größenanpassung von HashMap in Java wird das Element in Bucket, das in der verknüpften Liste gespeichert ist, während der Migration in den neuen Bucket umgekehrt, da java HashMap das neue Element nicht am Ende anfügt, sondern ein neues Element am Anfang anfügt Vermeiden Sie das Überfahren des Hecks. Wenn eine Race-Bedingung auftritt, erhalten Sie eine Endlosschleife
Ich habe zwei Fragen nach dem Lesen:
Bitte helfen Sie mir, dies zu klären, sehr geschätzt!
Tatsächlich gibt es mindestens eine Race-Bedingung für rehashing . Sehen Sie sich dieses Codefragment an (es stammt von Sun JDK7):
%Vor% Hier ist es möglich, dass Thread T1 mit rehash = true
endet und Thread T2 mit rehash = false
endet (angenommen, T1 hat bereits den Wert von this.useAltHashing
geändert).
Nun rate mal, welcher Thread den this.table
schreibt - du hast keine Ahnung, kann beides. Also, es ist eine Frage des Glücks, ob Sie einen konsistenten internen Zustand erhalten oder nicht.
Wie ich bereits in meinem Kommentar erwähnt habe, sollte HashMap nicht in einer Multithread-Umgebung verwendet werden . Es wird nicht funktionieren. Entweder aus diesem Grund oder aus anderen Gründen. Das oben genannte war nur ein Beispiel, warum Sie nicht versuchen sollten, gegen die Verträge zu gehen.
Die Antwort auf Ihre erste Frage finden Sie im zitierten Text:
"weil java HashMap das neue Element nicht an den Schwanz anfügt, sondern ein neues Element an den Kopf anfügt, um zu vermeiden, dass der Schwanz"
Wenn HashMap sie in Einfügereihenfolge speichern würde, müsste sie die Liste bei jeder Einfügung durchlaufen oder einen zusätzlichen Zeiger am Ende der Liste speichern (und beibehalten). Jedenfalls würde das Speichern der Elemente in dem Bucket in der Einfügereihenfolge keine Vorteile bringen (zumindest kann ich mir keine vorstellen).
Die Antwort auf Ihre zweite Frage basiert hier:
Ich weiß nicht, ob das Beispiel gültig ist. Klar ist, dass es umsetzungsspezifisch ist. Ich denke, es vermisst auch das größere Bild.
HashMap
s Vertrag klare Staaten (betonen ihre ):
Wenn mehrere Threads gleichzeitig auf eine Hash-Map zugreifen und mindestens einer der Threads die Map strukturell ändert, muss extern synchronisiert werden. (Eine strukturelle Änderung ist jede Operation, die eine oder mehrere Zuordnungen hinzufügt oder löscht; lediglich das Ändern des Werts, der einem Schlüssel zugeordnet ist, der bereits in einer Instanz enthalten ist, ist keine strukturelle Änderung.)
Wenn Sie den Vertrag brechen, sind alle Wetten deaktiviert. Die Karte kann auf beliebige, nicht näher spezifizierte Art und Weise explodieren.