ConcurrentHashMap gibt einen schwach konsistenten Iterator zurück, warum sollten wir ihn trotzdem verwenden?

8

Ich lese das Buch Java Concurrecny in der Praxis. Auf Seite 85 Abschnitt 5.2.1 wird über die ConcurrentHashMap und ihre Vorteile gesprochen. In einem Teil behaupten die Bücher jedoch, dass

  

Die von ConcurrentHashMap zurückgegebenen Iteratoren sind schwach konsistent. Dies   bedeutet, dass dieser Iterator gleichzeitige Änderung tolerieren kann,   traverses Elemente wie sie existierten, als Iterator konstruiert wurde, und   kann (aber nicht garantiert) Änderungen an der Sammlung widerspiegeln   nach der Konstruktion des Iterators.

Aus dem Grund, warum ich den ganzen Punkt der Synchronisation in konkurrierenden Programmen verstehe, ist es dem Thread zu erlauben, auf eine gemeinsam genutzte Ressource auf konsistente Weise zuzugreifen, während ConcurrentHashMap dies nicht wirklich erfüllt. Warum dann überhaupt?

    
Hossein 29.12.2012, 17:22
quelle

3 Antworten

16

Der Punkt ist die Vermeidung Synchronisation, wenn Sie sie nicht brauchen. Wenn es Ihnen nichts ausmacht, in einigen Fällen neue Elemente zu sehen und sie nicht in anderen zu sehen, kann der Iterator von ConcurrentHashMap erheblich billiger sein als entweder und verhindert, dass andere Threads Elemente hinzufügen, während Sie iterieren oder nehmen einen konsistenten Snapshot, wenn der Iterator erstellt wird.

Wenn Sie also eine Synchronisation und einen konsistenten Iterator benötigen, brauchen Sie eine Alternative - aber wenn Sie dies nicht tun, können Sie den effizienteren Iterator von ConcurrentHashMap nutzen.

    
Jon Skeet 29.12.2012, 17:25
quelle
1

ConcurrentHashMap soll vertraglich threadsicher sein. Es ist jedoch nicht konsistent über Threads .

Wenn Sie über eine ConcurrentHashMap iterieren, greift der Iterator eine Kopie der Hash-Map in dem Moment, in dem Sie danach gefragt haben (und diese Kopie wird thread-sicher erstellt) und Sie über diese Kopie iterieren. Und ja, nichts garantiert Ihnen das , während Sie über diese Kopie iterieren , einige Karteneinträge werden nicht entfernt. Aber die Map-Einträge, die auf diese Weise entfernt werden würden, existieren noch in Ihrem Iterator .

    
fge 29.12.2012 17:28
quelle
1

Alles hängt davon ab, wie stark Sie konsistent sind. Wenn Sie starke brauchen - als Mutexe oder andere Teilmenge von Operationen bieten würde, was Sie brauchen.

Manchmal benötigen Sie jedoch viel schwächere Anforderungen, aber Sie müssen zum Beispiel eine blockfreie Eigenschaft angeben, um den Durchsatz zu gewährleisten. Auf der anderen Seite benötigen Sie möglicherweise keine Iteratoren oder haben viel schwächere Einschränkungen für sie.

Wenn also alles, was Sie brauchen, eine Karte ist, die über Threads ConcurrentHashMap geteilt wird (sagen Sie Platz im Theater, wenn die Person es bucht), was Sie brauchen - und es kann viel schneller sein, wenn Sie viele Arbeitsfäden haben, da Sie Mutex-Synchronisation vermeiden. Auf der anderen Seite ist die Geschwindigkeit mit Kosten verbunden - die von Iterator zur Verfügung gestellte Ansicht entspricht nicht dem Zustand der Sammlung bei ihrer Erstellung und sie kann einige nachträglich erzeugte Elemente vermissen (im Allgemeinen in Multiprozessorsystemen ist happens-before relation schwierig) / p>

Bearbeiten : Als Prinz John Wesley darauf hinwies, dachte ich beim Lesen und Schreiben an ConcurrentSkipListMap . %Code%. Die meisten Punkte bestehen immer noch mit Ausnahme der Teile, die frei von Sperren sind (sowie alles, was davon kommt, wie garantierter Durchsatz, etc.).

    
Maciej Piechotka 29.12.2012 17:30
quelle