webentwicklung-frage-antwort-db.com.de

std :: lock_guard oder std :: scoped_lock?

C++ 17 führte eine neue Sperrklasse mit dem Namen std::scoped_lock .

Gemessen an der Dokumentation sieht es ähnlich aus wie das bereits existierende std::lock_guard Klasse.

Was ist der Unterschied und wann sollte ich es verwenden?

93
inf

Der einzige und wichtige Unterschied ist, dass std::scoped_lock Einen variablen Konstruktor hat, der mehr als einen Mutex akzeptiert. Auf diese Weise können mehrere Mutexe in einer Deadlock-Vermeidung gesperrt werden, als ob std::lock Verwendet würde.

{
    // safely locked as if using std::lock
    std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);     
}

Zuvor mussten Sie ein wenig tanzen, um mehrere Mutexe auf sichere Weise zu sperren, indem Sie std::lock Wie erläutert verwenden diese Antwort .

Das Hinzufügen einer Bereichssperre erleichtert die Verwendung und vermeidet die damit verbundenen Fehler. Sie können std::lock_guard Als veraltet betrachten. Der einzelne Argumentfall von std::scoped_lock Kann als Spezialisierung implementiert werden, sodass Sie keine Angst vor möglichen Leistungsproblemen haben müssen.

GCC 7 hat bereits Unterstützung für std::scoped_lock, Was zu sehen ist hier .

Weitere Informationen finden Sie im Standardpapier

58
inf

Der scoped_lock Ist eine streng überlegene Version von lock_guard, Die eine beliebige Anzahl von Mutexen auf einmal sperrt (unter Verwendung des gleichen Deadlock-Vermeidungsalgorithmus wie std::lock). In neuem Code sollten Sie immer nur scoped_lock Verwenden.

Der einzige Grund, warum lock_guard Noch besteht, ist die Kompatibilität. Es konnte nicht einfach gelöscht werden, da es im aktuellen Code verwendet wird. Darüber hinaus erwies es sich als unerwünscht, seine Definition zu ändern (von unär auf variabel), da dies ebenfalls eine beobachtbare und damit brechende Änderung ist (allerdings aus etwas technischen Gründen).

81
Kerrek SB

Hier ist ein Beispiel und ein Zitat aus C++ Concurrency in Action:

friend void swap(X& lhs, X& rhs)
{
    if (&lhs == & rhs)
        return;
    std::lock(lhs.m, rhs.m);
    std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
    std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock);
    swap(lhs.some_detail, rhs.some_detail);
}

vs.

friend void swap(X& lhs, X& rhs)
{
    if (&lhs == &rhs)
        return;
    std::scoped_lock guard(lhs.m, rhs.m);
    swap(lhs.some_detail, rhs.some_detail);
}

Das Vorhandensein von std::scoped_lock Bedeutet, dass die meisten Fälle, in denen Sie std::lock Vor c ++ 17 verwendet hätten, jetzt mit std::scoped_lock Geschrieben werden können. was nur gut sein kann!

3
陳 力