C++ 17 a introduit une nouvelle classe de verrouillage appelée std::scoped_lock
.
À en juger par la documentation, elle ressemble à la classe _std::lock_guard
_ déjà existante.
Quelle est la différence et quand devrais-je l'utiliser?
La différence unique et importante est que std::scoped_lock
a un constructeur variadique prenant plus d'un mutex. Cela permet de verrouiller plusieurs mutex de manière bloquée en évitant comme si std::lock
était utilisé.
{
// safely locked as if using std::lock
std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);
}
Auparavant, vous deviez faire une petite danse pour verrouiller plusieurs mutex de façon sûre en utilisant std::lock
comme expliqué cette réponse .
L'ajout du verrouillage de la portée facilite l'utilisation et évite les erreurs associées. Vous pouvez considérer std::lock_guard
obsolète. Le cas à un seul argument de std::scoped_lock
peut être implémenté en tant que spécialisation et vous permet de ne pas craindre d'éventuels problèmes de performances.
GCC 7 supporte déjà std::scoped_lock
qui peut être vu ici .
Pour plus d’informations, vous pouvez lire le papier standard
Le scoped_lock
est une version strictement supérieure de lock_guard
qui verrouille simultanément un nombre arbitraire de mutex (en utilisant le même algorithme d’évitement des blocages que std::lock
). Dans le nouveau code, vous ne devriez jamais utiliser que scoped_lock
.
La seule raison pour laquelle lock_guard
existe toujours est pour des raisons de compatibilité. Il ne peut pas simplement être supprimé, car il est utilisé dans le code actuel. De plus, il s'est avéré indésirable de changer sa définition (de unaire à variadique), car il s'agit également d'un changement observable, et donc décisif, (mais pour des raisons quelque peu techniques).
Voici un exemple et une citation de 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);
}
L’existence de
std::scoped_lock
signifie que la plupart des cas où vous auriez utiliséstd::lock
avant c ++ 17 peuvent désormais être écrits avecstd::scoped_lock
, avec moins de risque d’erreurs, qui ne peuvent que être une bonne chose!