Ich möchte die neuen Standard-Threads anstelle von boost: threads verwenden, aber ich habe bemerkt, dass die alte shared_mutex nicht verfügbar ist. Was wäre eine gute Empfehlung, diese Funktionalität zu ersetzen und mir ein Multi-Reader-, Single-Writer-Lock zu geben?Eine RW-Sperre für C++ 11 Threads
Antwort
std::shared_mutex
wird Teil der C++ 14 Standardbibliothek sein. Es ist nicht zu C++ 11 gekommen, nur weil es keine Zeit gab, einen Vorschlag zu formulieren und ihn gründlich zu diskutieren.
Sie können immer noch boost::shared_mutex
verwenden. Wenn Sie unter Windows mit Windows Vista oder höher arbeiten, können Sie Slim Read-Write Locks verwenden, die für Geschwindigkeit und Speicherverbrauch optimiert sind.
Sie sollten einen Blick auf die Stapelüberlauffrage "C++11 equivalent to boost shared_mutex" werfen, und insbesondere auf die folgende verknüpfte E-Mail-Konversation: http://permalink.gmane.org/gmane.comp.lib.boost.devel/211180 (erläutert den Widerstand des C++ 11-Komitees für die Freigabe von shared_mutex). Auch das folgende Experiment zu Joe Duffys Weblog: http://www.bluebytesoftware.com/blog/2009/02/12/ReaderwriterLocksAndTheirLackOfApplicabilityToFinegrainedSynchronization.aspx.
Jedes Mal, wenn Sie eine Lese-/Schreibsperre in Betracht ziehen, stellen Sie sich die folgenden 6 Fragen. Wenn Sie auf "Nein" antworten können, dann machen Leser/Schreiber-Sperren Ihr Programm schlechter, nicht besser.
- Ist mein gemeinsames Objekt
const
? Ich habe in meinem Leben mehr inkorrekte Verwendungen vonshared_mutex
gesehen als richtige Verwendungen. Um eineshared_mutex
richtig zu verwenden, muss der Fall sein, dass Sie Ihre gemeinsamen Objekteconst
im Leser kritischen Abschnitt ohne Compilerbeschwerden deklarieren können. Ein "Consumer" ist nicht entspricht "jemand, der die Datenstruktur überhaupt nicht mutiert." - Sind meine kritischen Abschnitte wirklich lang? Sperren einer shared_mutex ist viel teurer als das Sperren eines regulären Mutex. Sie müssen ein Los der Arbeit in Ihrem kritischen Abschnitt haben, um den erhöhten Aufwand des Schlosses zu ersetzen erwerben/freigeben.
- Sollte meine kritischen Abschnitte so lang sein? Sie sollten sich fragen, ob Sie wirklich all diese Arbeit in einem kritischen Bereich tun müssen. Oft gibt es eine Reihe von Vorbereitungsarbeiten und/oder Arbeit, um das Rückkehrobjekt zu massieren, das die
const
Aufrufe an das gemeinsame Objekt umgibt. Ein Großteil dieser zusätzlichen Arbeit, die nicht auf dem Datenabhängigkeitspfad von der ersten Verwendung des gemeinsam genutzten Objekts bis zur letzten Verwendung des gemeinsam genutzten Objekts liegt, kann außerhalb des kritischen Abschnitts verschoben werden. - Ist Schlosskonflikt wirklich mein Leistungsproblem? Auch wenn Ihre kritischen Abschnitte lang sind, sollten Sie absolut sicher sein, dass es sich bei der Sperrenkonflikte um Ihr Leistungsproblem handelt. Wenn Sie keine signifikanten Sperrkonflikte feststellen, können Sie durch den Wechsel zu Lese-/Schreibschutzsperren nichts kaufen.
- Könnte ich meine Sperrkonflikte reduzieren, indem ich auf ein feinkörnigeres Sperrschema umschalte? Verwenden Sie eine einzelne Sperre, um mehrere Objekte zu schützen? Können Sie jedem Objekt ein eigenes Schloss geben?
- Ist das Verhältnis von Lesern zu Schreibern deutlich größer als 1: 1? Selbst wenn Ihre kritischen Abschnitte lang sind und Sperrkonflikte ein ernstes Problem darstellen, muss das Verhältnis von Lesern zu Schreibern extrem hoch sein, um Lese-/Schreibsperre zu erhalten. Die Höhe hängt von den Kosten für atomare Anweisungen auf Ihrer Hardware und der Qualität der jeweiligen Implementierungen ab. (Joe Duffy findet, dass er auf seiner Maschine ein Verhältnis von etwa 20: 1 Lesern benötigt: Autoren, um Leser/Schreiber-Sperren zu gewinnen.)
Obwohl diese Seite von Joe Duffy mit ein wenig Vorsicht gelesen werden muss. Die assumptin, dass, weil _one_ Implementierung von _one_ bestimmten Art von rw-Schloss (in .NET) in gewisser Weise verhält hat rw-Schlösser im Allgemeinen nicht viel tragen. Ein rw-lock muss nicht langsamer als ein kritisches Section-Objekt sein und muss CAS-Operationen nicht verwenden. Es gibt so viele Variationen, zum Beispiel muss es nicht fair sein (oder es muss). Abhängig von der Situation können rw-Locks sehr viel effizienter sein (2-3 Größenordnungen) als ein Mutex. Die Aufnahme auf dem R/W-Verhältnis ist zu komisch ... – Damon
... Die nehmen auf die 1 bis 20-Verhältnis ist komisch, zu. Es ist nicht wirklich etwas besonderes. Die Verwendung des falschen Werkzeugs für eine Aufgabe führt im besten Fall zu mittelmäßigen Ergebnissen. Das ist wie beschweren, dass mit 'std :: list' führt schlecht auf Random Access oder' std :: VECTOR' schlecht ab, wenn Millionen von Elementen an der Front eingesetzt wird. Wenn Ihre Reads _not_ nicht zahlenmäßig überzählig sind, dann sind natürlich rw-locks kein Gewinn (und möglicherweise ein Verlust). Aber das ist das falsche Werkzeug. – Damon
Duffy Beispiel für eine Anfrage in jedem 0,25 ms kommen (= 250,000ns) ist ein gutes zu eins. Dies ist ein "totaler Null-Stau" -Fall. Selbst wenn man über die exzessiven Kosten einer CAS-Operation nachdenkt (die typischerweise weniger als 25 ns beträgt), fällt mir das in diesem Zusammenhang auf. Eine moderne CPU wird nicht durch 4000 atomare Operationen pro Sekunde herausgefordert. – Damon
- 1. C++ 11 Threads mit clang
- 2. Verhindern, dass Threads in C++ stauen. 11
- 3. Verzögerter Start eines Threads in C++ 11
- 4. Do C++ 11 Threads bieten eine Möglichkeit für losgelöste Threads nach dem Beenden des Hauptthreads fortzusetzen?
- 5. Leistung von Threads in C++ 11
- 6. C++ 11 Thema: Mehrere Threads auf eine Zustandsvariable warten
- 7. Was hält C++ 11 für einen "Thread"?
- 8. Variable Anzahl von asynchronen Threads mit C++ 11
- 9. Python und C++ 11 für swig: wie aktivieren C++ 11
- 10. C++ 11 alternativ pthread_cond_timedwait
- 11. C++ 11 Threads mit geteilten Mutex und Klasseninstanz
- 12. Autotools check für C++ 11
- 13. Gemeinsame Variablen in C++ 11
- 14. boost :: thread_group in C++ 11?
- 15. Bietet C++ 11 Hashfunktionen für std :: type_info?
- 16. C++ 11 is_same type Merkmal für Vorlagen
- 17. C++ 11 Beschränkungen für Lambda Rückgabetyp
- 18. C# -Threads - Nachrichten zwischen Threads posten
- 19. C++ 11 Thread Fehler Laufzeit
- 20. Parameter/Speichertyp für ein C++ 11 Lambda
- 21. Migration nach C++ 11
- 22. Karte von Mutex C++ 11
- 23. boost :: any typeid Optimierung für C++ 11
- 24. Speicherverwaltung für Lambda in C++ 11
- 25. Beispiel für C++ 11 Template-Parameter fehlbindend?
- 26. Gibt es eine C++ 11 CSPRNG?
- 27. C++ 11 bewegen, wenn eine Sperre
- 28. C++ 11: Inkrement time_point um eine Sekunde
- 29. C++ 11 Lambda-Capture-Liste [=] eine Referenz
- 30. C++ 11 Reflexionsbibliothek
Ich denke, eine bessere doppelte https://stackoverflow.com/q/14306797/783510 wäre. Das aktuelle Duplikat fragt nach einer handgerollten Implementierung, während das andere nach einer standardisierten Lese-/Schreibsperre fragt. –