it-swarm.com.de

std :: unique_lock <std :: mutex> oder std :: lock_guard <std :: mutex>?

Ich habe zwei Anwendungsfälle.

A. Ich möchte den Zugriff von zwei Threads auf eine Warteschlange synchronisieren.

B. Ich möchte den Zugriff von zwei Threads auf eine Warteschlange synchronisieren und eine Bedingungsvariable verwenden, da einer der Threads darauf wartet, dass der Inhalt vom anderen Thread in der Warteschlange gespeichert wird.

Für Anwendungsfall A sehe ich ein Codebeispiel mit std::lock_guard<> . Für Anwendungsfall B sehe ich ein Codebeispiel mit std::unique_lock<> .

Was ist der Unterschied zwischen den beiden und welchen soll ich in welchem ​​Anwendungsfall verwenden?

307
chmike

Der Unterschied besteht darin, dass Sie einen std::unique_lock Sperren und entsperren können. std::lock_guard Wird beim Bau nur einmal gesperrt und beim Zerstören entsperrt.

Für Anwendungsfall B benötigen Sie also definitiv einen std::unique_lock Für die Bedingungsvariable. Im Fall A hängt es davon ab, ob Sie die Schutzvorrichtung wieder verriegeln müssen.

std::unique_lock Verfügt über andere Funktionen, die es beispielsweise ermöglichen: ohne sofortiges Sperren des Mutex zu konstruieren, aber den RAII-Wrapper zu erstellen (siehe hier ).

std::lock_guard Bietet auch einen praktischen RAII-Wrapper, kann jedoch nicht mehrere Mutexe sicher sperren. Es kann verwendet werden, wenn Sie einen Wrapper für einen begrenzten Bereich benötigen, z. B .: eine Mitgliedsfunktion:

class MyClass{
    std::mutex my_mutex;
    void member_foo() {
        std::lock_guard<mutex_type> lock(this->my_mutex);            
        /*
         block of code which needs mutual exclusion (e.g. open the same 
         file in multiple threads).
        */

        //mutex is automatically released when lock goes out of scope           
};

Um eine Frage per chmike zu klären, sind std::lock_guard Und std::unique_lock Standardmäßig gleich. In diesem Fall können Sie std::lock_guard Durch std::unique_lock Ersetzen. Allerdings könnte std::unique_lock Etwas mehr Aufwand verursachen.

Beachten Sie, dass heutzutage std::scoped_lock anstelle von std::lock_guard Verwendet werden sollte.

299
inf

lock_guard und unique_lock sind so ziemlich dasselbe; lock_guard ist eine eingeschränkte Version mit einer eingeschränkten Benutzeroberfläche.

EIN lock_guard hält immer ein Schloss von seiner Konstruktion bis zu seiner Zerstörung. EIN unique_lock kann ohne sofortiges Sperren erstellt werden, kann zu jedem Zeitpunkt seines Bestehens entsperrt werden und kann das Eigentum an der Sperre von einer Instanz auf eine andere übertragen.

Also benutzt du immer lock_guard, es sei denn, Sie benötigen die Funktionen von unique_lock. EIN condition_variable braucht ein unique_lock.

102
Sebastian Redl

Verwenden lock_guard es sei denn, Sie müssen in der Lage sein, den dazwischen liegenden Mutex manuell zu unlock, ohne den lock zu zerstören.

Speziell, condition_variable gibt seinen Mutex frei, wenn er nach Aufrufen von wait in den Ruhezustand wechselt. Deshalb ist ein lock_guard ist hier nicht ausreichend.

43
ComicSansMS

Es gibt bestimmte Gemeinsamkeiten zwischen lock_guard und unique_lock und gewisse Unterschiede.

Im Kontext der gestellten Frage erlaubt der Compiler jedoch nicht die Verwendung eines lock_guard in Kombination mit einer Bedingungsvariablen, da der Mutex automatisch entsperrt wird, wenn ein Thread eine Bedingungsvariable wartet. Wenn andere Threads benachrichtigt werden und der aktuelle Thread aufgerufen wird (kein Warten mehr), wird die Sperre erneut aufgehoben. erworben.

Dieses Phänomen widerspricht dem Prinzip von lock_guard. lock_guard kann nur einmal konstruiert und nur einmal zerstört werden.

Daher lock_guard kann nicht in Kombination mit einer Bedingungsvariablen verwendet werden, sondern mit einem unique_lock kann sein (weil unique_lock kann mehrmals gesperrt und entsperrt werden).

9
Sandeep