Erstellen einer Standard-Map, die Thread-sicher ist

7

In meinem aktuellen Szenario ist Geschwindigkeit essentiell Ich habe eine Karte, die nur von mehreren Threads gelesen wird und das funktioniert gut. Jetzt kam eine Anforderung auf, die es erforderlich macht, gelegentlich in die statische Map zu schreiben, während die Maps von anderen Threads gelesen werden. Ich glaube, das ist ein Spiel Wechsler, da ich meine Karten für Thread-Sicherheit sperren müssen. Dies stellt ein Problem, da ich mehrere Threads 10-12 Threads haben, die die Karte lesen werden. Wenn eine Karte eine Sperre auf der Karte nimmt (seit dem Lesen), glaube ich, dass die Sperre notwendig wäre, da etwas in eine Karte geschrieben werden könnte. Wie auch schon gesagt, wenn eine Karte liest, haben andere Karten nicht den parallelen Lesezugriff auf die Karte wie früher. Gibt es eine Möglichkeit, dieses Problem zu umgehen?

    
MistyD 02.10.2013, 17:37
quelle

6 Antworten

12

Sie können ein shared_mutex neben Ihrer Karte verwenden, um freigegebenen oder eindeutigen Zugriff zu erhalten. Im Allgemeinen erfordert eine Schreiboperation einen eindeutigen Zugriff, während Leseoperationen einen gemeinsamen Zugriff erfordern.

Eine beliebige Anzahl von Threads kann gemeinsamen Zugriff erlangen, solange keine Threads eindeutigen Zugriff halten. Wenn ein Thread versucht, einen eindeutigen Zugriff zu erhalten, wartet er, bis der gesamte freigegebene Zugriff freigegeben ist.

Die Standardbibliothek und Boost bieten shared_lock<T> und unique_lock<T> für die bereichsbegrenzte Erfassung eines shared_mutex .

Beachten Sie, dass einige Leute behaupten, dass shared_mutex schlecht abschneidet, obwohl ich keine Beweise oder eine starke Analyse zur Unterstützung dieser Behauptungen gesehen habe. Es kann sich lohnen, nachzusehen, ob es Ihnen wichtig ist.

    
Collin Dauphinee 02.10.2013, 17:43
quelle
5

nur für Ihre C ++ Vergnügen, lesen Sie dieses Buch, finden Sie mehr Wert als das ausgegebene Geld, Ihre Nebenwelt Welt wird weit offen zu sein C ++ - Parallelität in Aktion Praktische Multithreading
Die Bücher befassen sich mit allen möglichen Problemen und praktischen Lösungen zwischen der gemeinsamen Nutzung von Threads, dem Erwecken von Threads, der Erstellung von Thread-Pools und mehr ... und mehr

hier ein Beispiel für die gemeinsame Nutzung von Daten zwischen Threads, ohne atomare oder shared_locks zu verwenden

%Vor%     
Sherlock 02.10.2013 17:50
quelle
4

Hier ist meine Implementierung von threadsafe generic resizable hashmap ohne Verwendung von STL-Containern:

%Vor%     
Andrushenko Alexander 15.08.2016 15:45
quelle
3

Eine der Lösungen könnte darin bestehen, einen Zeiger auf diese Map zu behalten, und wenn Sie sie modifizieren müssen - kopieren Sie, modifizieren Sie diese Kopie und tauschen Sie dann den Zeiger atomar gegen die neue Instanz aus. Diese Lösung würde mehr Speicher beanspruchen, könnte aber effizienter sein, wenn Sie viele Lese-Threads haben, da diese Methode frei von Sperren ist.

Im folgenden Beispiel kann nur ein Thread die Map ändern. Dies bedeutet nicht immer einen Thread, sondern ein und denselben Thread für die Lebensdauer der Datenstruktur. Andernfalls müsste die Änderung vorgenommen werden, während ein Mutex gehalten wird, der den gesamten Code in updateMap schützt. Die Leser-Threads können wie gewohnt auf theData zugreifen - ohne Sperren.

%Vor%     
Slava 02.10.2013 17:48
quelle
0

Die anderen zwei Antworten sind ziemlich gut, aber ich dachte, ich sollte ein bisschen Farbe hinzufügen:

Cliff Click hat eine blockierungsfreie gleichzeitige Hash-Map in Java geschrieben. Es wäre nicht sinnvoll, es an C ++ anzupassen (kein GC, anderes Speichermodell usw.), aber es ist die beste Implementierung einer blockierungsfreien Datenstruktur, die ich je gesehen habe. Wenn Sie JAVA anstelle von C ++ verwenden können, könnte dies der richtige Weg sein.

Ich kenne keine blockierungsfreien symmetrischen Binärbaumstrukturen. Das bedeutet nicht, dass sie nicht existieren.

Es ist wahrscheinlich am einfachsten, mit einer der beiden anderen Antworten zu gehen (Bulk-Kopie / Atom-Swap / etwas wie shared_ptr oder Leser-Schreiber-Locking), um stattdessen den Zugriff auf map zu steuern. Je nach den relativen Mengen von Lese- und Schreibvorgängen und der Größe von map ist einer der beiden Werte schneller. Sie sollten einen Benchmark erstellen, um zu sehen, welchen Sie verwenden sollten.

    
tmyklebu 02.10.2013 18:03
quelle
0

Was Sie brauchen, ist eine ConcurrentHashMap in Java, die gleichzeitiges Lesen und Schreiben in die zugrunde liegende Hashtabelle erlaubt. Diese Klasse ist Teil des Pakets java.util.concurrent und ermöglicht das gleichzeitige Lesen und Schreiben (bis zu einer Parallelitätsebene, standardmäßig 16).

Weitere Informationen finden Sie im javadoc . Ich zitiere den Javadoc hier:

  

Eine Hash-Tabelle, die vollständige Parallelität von Abfragen und einstellbaren erwarteten Parallelität für Aktualisierungen unterstützt. Diese Klasse entspricht der gleichen funktionalen Spezifikation wie Hashtable und enthält Methodenversionen, die jeder Hashtable-Methode entsprechen. Obwohl alle Vorgänge Thread-sicher sind, führen Abrufvorgänge nicht zum Sperren, und es gibt keine Unterstützung für das Sperren der gesamten Tabelle auf eine Weise, die allen Zugriff verhindert. Diese Klasse ist vollständig kompatibel mit Hashtable in Programmen, die auf der Thread-Sicherheit, aber nicht auf den Synchronisationsdetails beruhen.

    
inder 02.10.2013 17:53
quelle

Tags und Links