web-dev-qa-db-fra.com

std :: lock_guard ou std :: scoped_lock?

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?

93
inf

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

58
inf

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).

81
Kerrek SB

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 avec std::scoped_lock, avec moins de risque d’erreurs, qui ne peuvent que être une bonne chose!

3
陳 力