webentwicklung-frage-antwort-db.com.de

unordered_map Thread-Sicherheit

Ich verwende ein einzelnes Thread-Programm mithilfe der boost: thread-Bibliothek in Multi-Thread. Das Programm verwendet unordered_map als Hash_map für Suchvorgänge. Meine Frage ist.. 

Zu einer Zeit schreiben viele Threads, und zu einer anderen werden viele lesen, aber nicht gleichzeitig lesen und schreiben, d. H. Entweder alle Threads lesen oder alle schreiben. Ist das fadensicher und der Container dafür ausgelegt? Und wenn es so sein wird, wird es wirklich gleichzeitig sein und die Leistung verbessern? Muss ich einen Verriegelungsmechanismus verwenden?

Ich habe irgendwo gelesen, dass der C++ - Standard sagt, dass das Verhalten undefiniert ist, aber ist das alles?

UPDATE: Ich habe auch über Intel concurrent_hash_map nachgedacht. Ist das eine gute Option?

20
questions

STL-Container sind so konzipiert, dass Sie garantiert Folgendes haben:

A. Mehrere Threads gleichzeitig lesen

oder

B. Ein Thread gleichzeitig schreiben

Das Schreiben mehrerer Threads ist keine der oben genannten Bedingungen und ist nicht zulässig. Durch das Schreiben mehrerer Threads wird somit ein Datenrennen erstellt, das undefiniertes Verhalten ist.

Sie könnten einen Mutex verwenden, um dies zu beheben. Ein shared_mutex (kombiniert mit shared_locks) wäre besonders nützlich, da dieser Mutex-Typ mehrere gleichzeitige Leser zulässt.

http://eel.is/c++draft/res.on.data.races#3 ist der Teil des Standards, der die gleichzeitige Verwendung von const-Funktionen auf verschiedenen Threads garantiert. http://eel.is/c++draft/container.requirements.dataraces gibt einige zusätzliche Nicht-Konstantenoperationen an, die in verschiedenen Threads sicher sind.

40
Lalaland

Ist das fadensicher und der Container dafür ausgelegt?

Nein, die Standardbehälter sind nicht fadensicher.

Muss ich einen Verriegelungsmechanismus verwenden?

Ja, das tust du. Da Sie boost verwenden, wäre boost::mutex eine gute Idee. In C++ 11 gibt es std::mutex.

Ich habe irgendwo gelesen, dass der C++ - Standard sagt, dass das Verhalten undefiniert ist, aber ist das alles?

In der Tat ist das Verhalten undefiniert. Ich bin nicht sicher, was Sie mit "ist das alles?" Meinen, da undefiniertes Verhalten die schlechteste mögliche Art des Verhaltens ist und ein Programm, das es ausweist, per Definition falsch ist. Insbesondere bei falscher Thread-Synchronisierung ist es wahrscheinlich, dass es zu zufälligen Abstürzen und Datenverfälschungen kommt. Dies ist oft sehr schwierig zu diagnostizieren. Daher sollten Sie diese unbedingt um jeden Preis vermeiden.

UPDATE: Ich habe auch über Intel concurrent_hash_map nachgedacht. Ist das eine gute Option?

Es hört sich gut an, aber ich habe es selbst nie benutzt, daher kann ich keine Meinung dazu abgeben.

7
Mike Seymour

Die vorhandenen Antworten decken die wichtigsten Punkte ab:

  • sie müssen über eine Sperre verfügen, um die Karte lesen oder schreiben zu können
  • sie können eine Sperre für mehrere Leser/Einzelschreiber verwenden, um die Parallelität zu verbessern

Sie sollten auch wissen, dass:

  • wenn Sie einen zuvor abgerufenen Iterator oder einen Verweis oder Zeiger auf ein Element in der Karte verwenden, zählt dies als Lese- oder Schreiboperation

  • schreiboperationen, die in anderen Threads ausgeführt werden, können Zeiger/Referenzen/Iteratoren in der Map ungültig machen, genauso wie sie es wären, wenn sie in demselben Thread ausgeführt würden, selbst wenn erneut eine Sperre erlangt wird, bevor versucht wird, sie weiter zu verwenden.

3
Tony Delroy

std :: unordered_map erfüllt die Anforderungen von Container (ref http://en.cppreference.com/w/cpp/container/unordered_map ). Zur Sicherheit von Containerthreads siehe: http://en.cppreference.com/w/cpp/container#Thread_safety .

Wichtige Punkte:

  • "Verschiedene Elemente in demselben Container können gleichzeitig von verschiedenen Threads geändert werden."
  • "Alle const-Mitgliedsfunktionen können gleichzeitig von verschiedenen Threads im selben Container aufgerufen werden. Außerdem sind die Mitgliedsfunktionen begin (), end (), rbegin (), rend (), front (), back (), data (). find (), lower_bound (), upper_bound (), equal_range (), at () und, außer in assoziativen Containern, verhält sich operator [] im Sinne der Thread-Sicherheit als const (dh sie können auch aufgerufen werden gleichzeitig durch verschiedene Threads in demselben Container). "
1
Ida

Sie können concurrent_hash_map verwenden oder einen Mutex verwenden, wenn Sie auf unordered_map zugreifen. Ein Problem bei der Verwendung von intel concurrent_hash_map ist, dass Sie TBB hinzufügen müssen, aber Sie verwenden bereits boost.thread. Diese beiden Komponenten verfügen über eine überlappende Funktionalität und verkomplizieren daher Ihre Codebasis.

1
Chang