Ich habe eine Multithread-App, die einige Daten häufig lesen muss, und gelegentlich werden diese Daten aktualisiert. Momentan schützt ein Mutex den Zugriff auf diese Daten sicher, aber es ist teuer, weil ich möchte, dass mehrere Threads gleichzeitig lesen können und sie nur dann sperren, wenn ein Update erforderlich ist (der Update-Thread könnte warten, bis die anderen Threads abgeschlossen sind). .
Ich denke, das boost::shared_mutex
soll das sein, aber ich weiß nicht genau, wie ich es verwenden soll, und habe kein klares Beispiel gefunden.
Hat jemand ein einfaches Beispiel, mit dem ich anfangen könnte?
c++
multithreading
boost
mutex
boost-thread
kevin42
quelle
quelle
Antworten:
Es sieht so aus, als würden Sie so etwas tun:
quelle
1800 INFORMATIONEN sind mehr oder weniger korrekt, aber es gibt einige Probleme, die ich korrigieren wollte.
Beachten Sie außerdem, dass im Gegensatz zu einem shared_lock nur ein einzelner Thread gleichzeitig ein upgrade_lock erwerben kann, selbst wenn es nicht aktualisiert wurde (was ich als unangenehm empfand, als ich darauf stieß). Wenn alle Ihre Leser bedingte Autoren sind, müssen Sie eine andere Lösung finden.
quelle
boost::unique_lock< boost::shared_mutex > lock(lock);
lesenboost::unique_lock< boost::shared_mutex > lock(
_access);
?Seit C ++ 17 (VS2015) können Sie den Standard für Lese- / Schreibsperren verwenden:
Für ältere Versionen können Sie Boost mit derselben Syntax verwenden:
quelle
typedef boost::unique_lock< Lock > WriteLock; typedef boost::shared_lock< Lock > ReadLock;
.Um weitere empirische Informationen hinzuzufügen, habe ich das gesamte Problem der aktualisierbaren Sperren und das Beispiel für den Boost shared_mutex (mehrere Lesevorgänge / ein Schreibvorgang) untersucht. ist eine gute Antwort, wenn Sie die wichtige Information hinzufügen, dass nur ein Thread ein upgrade_lock haben kann, auch wenn es nicht aktualisiert wird. Dies ist wichtig, da Sie kein Upgrade von einer gemeinsam genutzten Sperre auf eine eindeutige Sperre durchführen können, ohne zuvor die gemeinsam genutzte Sperre aufzuheben. (Dies wurde an anderer Stelle diskutiert, aber der interessanteste Thread ist hier http://thread.gmane.org/gmane.comp.lib.boost.devel/214394 )
Ich habe jedoch einen wichtigen (undokumentierten) Unterschied zwischen einem Thread gefunden, der auf ein Upgrade auf eine Sperre wartet (dh darauf warten muss, dass alle Leser die gemeinsam genutzte Sperre aufheben), und einer Schreibsperre, die auf dasselbe wartet (dh einer unique_lock).
Der Thread, der auf einen unique_lock im shared_mutex wartet, blockiert alle neuen Leser, die hereinkommen. Sie müssen auf die Anforderung des Autors warten. Dies stellt sicher, dass Leser keine Schriftsteller verhungern (ich glaube jedoch, dass Schriftsteller Leser verhungern könnten).
Der Thread, der darauf wartet, dass ein upgradeeable_lock aktualisiert wird, ermöglicht es anderen Threads, eine gemeinsame Sperre zu erhalten, sodass dieser Thread möglicherweise ausgehungert wird, wenn die Leser sehr häufig sind.
Dies ist ein wichtiges Thema, das zu berücksichtigen ist und wahrscheinlich dokumentiert werden sollte.
quelle
Terekhov algorithm
stellt sicher, dass1.
der Autor die Leser nicht verhungern kann. Sehen Sie das . Ist2.
aber wahr. Ein upgrade_lock garantiert keine Fairness. Sehen Sie das .Verwenden Sie ein Semaphor mit einer Anzahl, die der Anzahl der Leser entspricht. Lassen Sie jeden Leser eine Zählung des Semaphors nehmen, um zu lesen, so dass alle gleichzeitig lesen können. Lassen Sie dann den Verfasser vor dem Schreiben ALLE Semaphorzählungen vornehmen. Dies führt dazu, dass der Writer wartet, bis alle Lesevorgänge abgeschlossen sind, und dann die Lesevorgänge beim Schreiben blockiert.
quelle
Die großartige Antwort von Jim Morris, ich bin darauf gestoßen und es hat eine Weile gedauert, bis ich es herausgefunden habe. Hier ist ein einfacher Code, der zeigt, dass nach dem Senden einer "Anfrage" für einen unique_lock-Boost (Version 1.54) alle shared_lock-Anfragen blockiert werden. Dies ist sehr interessant, da es mir so scheint, als ob die Wahl zwischen unique_lock und upgradeeable_lock es erlaubt, wenn wir Schreibpriorität oder keine Priorität wünschen.
Auch (1) in Jim Morris 'Beitrag scheint dem zu widersprechen: Boost shared_lock. Bevorzugt lesen?
quelle