C ++ 17 a introduit une nouvelle classe de verrouillage appelée std::scoped_lock
.
À en juger par la documentation, il ressemble à la std::lock_guard
classe déjà existante .
Quelle est la différence et quand dois-je l'utiliser?
la source
C ++ 17 a introduit une nouvelle classe de verrouillage appelée std::scoped_lock
.
À en juger par la documentation, il ressemble à la std::lock_guard
classe déjà existante .
Quelle est la différence et quand dois-je l'utiliser?
Il scoped_lock
s'agit d'une version strictement supérieure de lock_guard
qui verrouille un nombre arbitraire de mutex en même temps (en utilisant le même algorithme d'évitement de blocage que std::lock
). Dans le nouveau code, vous ne devriez jamais utiliser scoped_lock
.
La seule raison lock_guard
existe encore est la compatibilité. Il ne pouvait 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 c'est aussi un changement observable, et donc cassant (mais pour des raisons quelque peu techniques).
lock_guard
. Mais cela rend certainement les classes de garde un peu plus faciles à utiliser.La seule et importante différence est qu'un
std::scoped_lock
constructeur variadique prend plus d'un mutex. Cela permet de verrouiller plusieurs mutex de manière à éviter les interblocages comme s'ilsstd::lock
étaient utilisés.Auparavant, vous deviez faire une petite danse pour verrouiller plusieurs mutex de manière 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 comme
std::lock_guard
obsolète. Le cas d'argument unique destd::scoped_lock
peut être implémenté en tant que spécialisation et vous n'avez donc pas à craindre d'éventuels problèmes de performances.GCC 7 a déjà un support pour
std::scoped_lock
lequel peut être vu ici .Pour plus d'informations, vous voudrez peut-être lire l' article standard
la source
scoped_lock lk; // locks all mutexes in scope
. LGTM.scoped_lock lk;
est le nouveau raccourci pourscoped_lock<> lk;
. Il n'y a pas de mutex. Alors tu as raison. ;-)Réponse tardive, et principalement en réponse à:
Pour le cas courant où l'on a besoin de verrouiller exactement un mutex,
std::lock_guard
dispose d'une API qui est un peu plus sûre à utiliser quescoped_lock
.Par exemple:
L'extrait ci-dessus est probablement une erreur d'exécution accidentelle car il se compile et ne fait absolument rien. Le codeur voulait probablement dire:
Maintenant, il se verrouille / se déverrouille
mut
.Si a
lock_guard
été utilisé dans les deux exemples ci-dessus à la place, le premier exemple est une erreur de compilation au lieu d'une erreur d'exécution, et le deuxième exemple a des fonctionnalités identiques à la version qui utilisescoped_lock
.Mon conseil est donc d'utiliser l'outil le plus simple pour le travail:
lock_guard
si vous avez besoin de verrouiller exactement 1 mutex pour une étendue entière.scoped_lock
si vous avez besoin de verrouiller un nombre de mutex différent de 1.unique_lock
si vous avez besoin de déverrouiller dans le cadre du bloc (qui comprend l'utilisation avec acondition_variable
).Ce conseil n'implique pas qu'il
scoped_lock
devrait être repensé pour ne pas accepter 0 mutex. Il existe des cas d'utilisation valides où il est souhaitablescoped_lock
d'accepter des packs de paramètres de modèles variadiques qui peuvent être vides. Et la valise vide ne doit rien verrouiller.Et c'est pourquoi
lock_guard
n'est pas obsolète.scoped_lock
etunique_lock
peut être un sur-ensemble de fonctionnalités delock_guard
, mais ce fait est une arme à double tranchant. Parfois, ce qu'un type ne fera pas est tout aussi important (construction par défaut dans ce cas).la source
Voici un exemple et une citation de C ++ Concurrency en action :
contre.
la source