422 votes

std::unique_lock<std::mutex> ou std::lock_guard<std::mutex>?</std::mutex> </std::mutex>

J'ai deux cas d'utilisation.

A. je veux synchroniser l'accès par deux fils à une file d'attente.

B. je veux synchroniser l'accès par deux fils à une file d'attente et d'utiliser une variable de condition, car l'un des threads en attente sur le contenu pour être stocké dans la file d'attente par l'autre thread.

Pour le cas d'utilisation d'Un je voir exemple de code à l'aide de std::lock_guard<>. Pour les cas d'utilisation B I voir exemple de code à l'aide de std::unique_lock<>.

Quelle est la différence entre les deux et qui dois-je utiliser dans lequel cas d'utilisation?

408voto

bamboon Points 7089

La différence est que vous pouvez verrouiller et déverrouiller un std::unique_lock. std::lock_guard sera verrouillé qu'une seule fois sur la construction et déverrouillé à la destruction.

Donc, pour les cas d'utilisation B vous avez certainement besoin d'un std::unique_lock pour la variable de condition. Dans le cas où Un cela dépend si vous avez besoin de relock le garde.

std::unique_lock a d'autres fonctions qui permettent, par exemple: être construit sans verrouiller le mutex immédiatement, mais pour construire le RAII wrapper (voir ici).

Verrouillage des gardes peut être utilisé lorsque vous avez simplement besoin d'un wrapper pour une portée limitée, par exemple: une fonction de membre:

void member_foo() {
    std::lock_guard<mutex_type> lock(this->my_mutex);
    ...
}

Afin de clarifier une question par chmike, par défaut std::lock_guard et std::unique_lock sont même. Ainsi, dans le cas ci-dessus, vous pouvez remplacer std::lock_guard avec std::unique_lock. Toutefois, std::unique_lock pourrait avoir un peu plus de surcharge.

146voto

Sebastian Redl Points 18816

lock_guard et unique_lock sont à peu près la même chose; lock_guard est une version restreinte avec une interface limitée.

Un lock_guard toujours détient un verrou de sa construction à sa destruction. Un unique_lock peut être créé sans immédiatement de verrouillage, pouvez le déverrouiller en un point quelconque de son existence, et peut transférer la propriété de la serrure d'une instance à l'autre.

Si vous utilisez toujours lock_guard, sauf si vous avez besoin des capacités d' unique_lock. Un condition_variable besoin d'un unique_lock.

57voto

ComicSansMS Points 12749

Utilisation à moins que vous devez être en mesure de manuellement le mutex reste sans détruire la `` .

En particulier, déverrouille le mutex quand aller dormir sur les appels à . C’est pourquoi un `` ne suffit pas ici.

11voto

Sandeep Points 100

Il y a certaines choses en commun entre lock_guard et unique_lock et de certaines différences. Mais dans le contexte de la question posée, le compilateur ne permet pas l'utilisation d'un lock_guard en combinaison avec une variable de condition, parce que quand un thread appelle attendre sur une variable de condition, le mutex obtient automatiquement déverrouillées et lorsque d'autres thread/threads informer et le thread courant est invoquée (provient d'attente), le verrouillage est acquis. Ce phénomène est à l'encontre du principe de lock_guard. lock_guard peut être construit qu'une seule fois et détruits qu'une seule fois.

Donc lock_guard ne peut pas être utilisé en combinaison avec une variable de condition, mais un unique_lock peut-être (parce que unique_lock peut être verrouillé ou déverrouillé à plusieurs reprises).

-5voto

Chris Vine Points 137

Comme il a été mentionné par d'autres, std::unique_lock pistes de l'état verrouillé de l'mutex, de sorte que vous pouvez reporter de verrouillage jusqu'à ce que après la construction de la verrouiller et déverrouiller avant la destruction de la serrure. std::lock_guard ne le permet pas.

Il n'y a aucune raison pourquoi les std::condition_variable attendre fonctions ne devrait pas prendre une lock_guard ainsi que d'un unique_lock, parce que chaque fois qu'une attente se termine (pour quelque raison que ce soit) le mutex est automatiquement rétabli afin de ne pas provoquer de toute violation sémantique. Toutefois, selon la norme, d'utiliser un std::lock_guard avec une variable de condition, vous devez utiliser un std::condition_variable_any au lieu de std::condition_variable.

Edit: supprimé "à l'Aide de la pthreads interface std::condition_variable et std::condition_variable_any doivent être identiques". Sur la recherche à gcc de mise en œuvre:

  • std::condition_variable::wait(std::unique_lock&) appels pthread_cond_wait() sur une variable de condition pthread à l'égard des mutex détenus par unique_lock (et donc, on pourrait aussi faire de même pour lock_guard, mais n'est pas parce que la norme ne prévoit pas que)
  • std::condition_variable_any peut travailler avec n'importe quel objet verrouillable, dont un qui n'est pas un mutex lock (il pourrait même travailler avec un inter-processus de sémaphore)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X