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?
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
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).
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 Siestd::lock
Vor c ++ 17 verwendet hätten, jetzt mitstd::scoped_lock
Geschrieben werden können. was nur gut sein kann!