web-dev-qa-db-fra.com

std :: scoped_lock ou std :: unique_lock ou std :: lock_guard?

De - this question que je comprends que std::scoped_lock est "une version strictement supérieure de std::lock_guard ".

De - this question que je comprends que "std::lock_guard et std::unique_lock sont les mêmes "sauf que std::unique_lock a des caractéristiques supplémentaires (par exemple, try_lock ) au coût d'une augmentation supplémentaire.

Comment std::scoped_lock comparer avec std::unique_lock?

Quelques questions connexes que j'espère avoir répondu par cette question.

  1. Quelles sont les différences entre std::scoped_lock et std::unique_lock?
  2. Dans quelles situations devriez-vous utiliser std::scoped_lock à la place de std::unique_lock?
  3. Dans quelles situations devriez-vous utiliser std::unique_lock à la place de std::scoped_lock?
  4. Pourquoi est-ce que std::scoped_lock ne pas mettre en œuvre certaines des fonctionnalités supplémentaires de std::unique_lock?
14
lachy

Les deux objets sont à des fins différentes. scoped_lock est pour le cas simple de vouloir verrouiller un certain nombre d'objets mutex de manière sans impasse. Verrouiller un seul mutex n'est qu'un cas particulier de verrouillage multiple. L'objet est complètement immobile et c'est très simple.

unique_lock fournit un certain nombre de fonctionnalités, dont peu sont particulièrement applicables lorsqu'ils verrouillent simultanément multiples mutexes.

  • Verrouillage différé. Le report devrait être tout ou rien; Vous différerez soit verrouillant tous les mutiles ou aucun d'entre eux. Ce n'est pas clair pourquoi vous voudriez différer de verrouiller une série de mutexs, car vous devriez renoncer à tous les écluses qui ont réussi le cas échéant.

  • Serrures du délai d'attente. Si vous voulez un délai d'attente de 100 ms, cela signifie-t-il que le verrouillage de tous les mutiles ne doit pas prendre plus de 100 ms? C'est-à-dire que si les 3 premiers verrouillent immédiatement, mais le prochain prend 75 ms, devrait-il être considéré comme un délai d'attente si la cinquième prend 30 ms?

  • Adoption de mautexes. L'ensemble du point de verrouillage de multiples mutiles en une seule opération est de pouvoir éviter les blocages. Ceci est fait en verrouillant les mutiles dans un ordre globalement cohérent. C'est-à-dire n'importe quel endroit où vous verrouillez ces objets mutex avec std::lock Les appels équivalents les verront dans le même ordre, peu importe quoi.

    Si l'un des mutiles a déjà été verrouillé (et donc le verrou doit être adopté), il a été verrouillé à l'extérieur de std::lock, et vous n'avez donc aucune garantie qu'il a été enfermé dans l'ordre globalement cohérent. Et cela ignore la difficulté de spécifier les mutiles à adopter et lesquels à verrouiller.

  • Transfert de propriété (être mobile). Il s'agit d'une perspective douteuse de multiples mutiles pour des raisons similaires que l'adoption de verrous. Les garanties sur des blocages ne fonctionnent que si un seul appel à std::lock ou équivalent verrouille tous les mutiles d'intérêt. Si vous déplacez la propriété de ces scoped_locks autour, il devient très facile d'être à un point de code où vous avez plusieurs scoped_locks dans la même portée, lorsque vous auriez pu les enfermer tous en une seule fois. Cela court le genre d'impasse que std::lock a été créé pour éviter.

Notez que std::lock (la base de scoped_lock la fonctionnalité) n'essaie même pas de fournir aucune de ces fonctionnalités.

Pourrait-il y avoir une spécialisation de scoped_lock qui n'a pris qu'un seul type mutex offrant le comportement de unique_lock? Sûr. Mais cela violerait le but de scoped_lock, qui devait être un casier sans module de refuge pour plusieurs mutiles. Il a seulement obsolète lock_guard Par accident, puisqu'il avait l'interface identique dans le cas d'un seul mutex.

En outre, avoir des spécialisations de gabarits avec des interfaces et des capacités très différentes ne fonctionnent généralement pas bien. Voir vector<bool> par exemple.

5
Nicol Bolas