2013-05-27 15 views
20

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

+1

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. –

Antwort

21

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.

+0

pThreads hat auch 'pthread_rwlock' auf Linux – pyCthon

+5

[std :: shared_mutex] (http://en.cppreference.com/w/cpp/thread/shared_mutex) ist nicht in C++ 14, wird es in C++ 17. – Deqing

12

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.

  1. Ist mein gemeinsames Objekt const? Ich habe in meinem Leben mehr inkorrekte Verwendungen von shared_mutex gesehen als richtige Verwendungen. Um eine shared_mutex richtig zu verwenden, muss der Fall sein, dass Sie Ihre gemeinsamen Objekte const im Leser kritischen Abschnitt ohne Compilerbeschwerden deklarieren können. Ein "Consumer" ist nicht entspricht "jemand, der die Datenstruktur überhaupt nicht mutiert."
  2. 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.
  3. 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.
  4. 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.
  5. 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?
  6. 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.)
+3

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

+2

... 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

+1

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