Hashmap in einer Multithread-Umgebung beim Ändern der Größe

8

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:

  1. Warum wird die verknüpfte Liste für jeden Bucket in der Reihenfolge umgekehrt?
  2. Ich kann sehen, dass es eine Race Condition geben könnte, aber kann nicht sehen, wie die Endlosschleife kommt? Liegt es daran, dass ein Thread das Element Kopf an den Schwanz anfügt, während der andere es in umgekehrter Reihenfolge macht?

Bitte helfen Sie mir, dies zu klären, sehr geschätzt!

    
Kevin 12.04.2013, 14:24
quelle

3 Antworten

2

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.

    
gaborsch 12.04.2013, 14:37
quelle
9

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:

Ссылка

    
Nándor Krácser 12.04.2013 17:43
quelle
0

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.

    
NPE 12.04.2013 14:37
quelle

Tags und Links