C++11: pourquoi std::condition_variable utiliser std::unique_lock?
Je suis un peu confus sur le rôle de std::unique_lock
lorsque l'on travaille avec std::condition_variable
. Que j'ai compris le la documentation, std::unique_lock
est fondamentalement un ballonnement de verrouillage de la garde, avec la possibilité d'échanger de l'état entre deux écluses.
Je n'ai jusqu'à présent utilisé pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
à cette fin (je suppose que c'est ce que la STL utilise sur posix). Il prend un mutex, pas un verrou.
Quelle est la différence ici? C'est le fait que std::condition_variable
traite std::unique_lock
une optimisation? Si oui, comment exactement est-il plus rapide?
- Êtes-vous confus au sujet de pourquoi vous avez besoin d'un verrouillage/mutex avec une variable de condition, ou à propos de la différence entre, d'une serrure et d'un mutex ou pourquoi une variable de condition utilise un unique de verrouillage et pas un mutex?
- "pourquoi une variable de condition utilise un unique de verrouillage et pas un mutex" ce.
Vous devez vous connecter pour publier un commentaire.
Je upvoted cmeerw de répondre parce que je crois qu'il a donné une raison technique. Nous allons marcher à travers elle. Imaginons que le comité avait décidé d'avoir
condition_variable
attendre sur unmutex
. Voici le code à l'aide de cette conception:C'est exactement la façon dont un ne devrait pas utiliser un
condition_variable
. Dans les régions marqué avec:il y a une exception problème de sécurité, et il est sérieux. Si une exception est levée dans ces domaines (ou par
cv.wait
lui-même), l'état verrouillé de l'mutex est une fuite à moins d'un try/catch est aussi mettre en quelque part pour intercepter l'exception et le déverrouiller. Mais c'est juste plus de code que vous demandez au programmeur d'écrire.Disons que le programmeur sait comment écrire exception coffre-fort à code, et sait s'en servir
unique_lock
pour l'atteindre. Maintenant, le code ressemble à ceci:C'est beaucoup mieux, mais il n'est toujours pas une grande situation. Le
condition_variable
interface est de faire le programmeur de sortir de sa façon de faire les choses à travailler. Il est possible de déréférencement de pointeur null silk
accidentellement ne fait pas référence à un mutex. Et il n'existe aucun moyen pourcondition_variable::wait
pour vérifier que ce thread n'propre de la serrure surmut
.Oh, viens de me rappeler, il y a également le risque que le programmeur peut choisir le mal
unique_lock
fonction membre pour exposer le mutex.*lk.release()
serait désastreux ici.Regardons maintenant comment le code est écrit avec le réel
condition_variable
API qui prend ununique_lock<mutex>
:wait
fonction peut vérifierlk.owns_lock()
et de lever une exception si elle estfalse
.Ces techniques sont les raisons qui ont conduit à la conception d'API de
condition_variable
.En outre,
condition_variable::wait
ne pas prendre unlock_guard<mutex>
parce quelock_guard<mutex>
est de savoir comment vous dire: je possède le verrou sur ce mutex jusqu'àlock_guard<mutex>
détruise. Mais lorsque vous appelezcondition_variable::wait
, vous implicitement libérer le verrou sur le mutex. De sorte que l'action est incompatible avec lalock_guard
cas d'utilisation /déclaration.Nous avons besoin
unique_lock
de toute façon que l'on pourrait, de retour de serrures de fonctions, de les mettre dans des conteneurs, et de verrouiller/déverrouiller les mutex hors de portée des modèles dans une exception en toute sécurité, de sorteunique_lock
était le choix naturel pourcondition_variable::wait
.Mise à jour
bamboon suggéré dans les commentaires ci-dessous que j'ai contraste
condition_variable_any
, voilà:Question: Pourquoi n'est-ce pas
condition_variable::wait
basé sur un modèle afin que je puisse passer touteLockable
de texte?Réponse:
C'est vraiment cool d'avoir. Par exemple ce document montre le code qui attend une
shared_lock
(rwlock) en mode partagé sur une variable de condition (quelque chose inouïe dans l'posix monde, mais très utile par ailleurs). Toutefois, la fonctionnalité est plus cher.De sorte que le comité a introduit un nouveau type avec cette fonctionnalité:
Avec cette
condition_variable
adaptateur l'on peut attendre sur tout verrouillable type. Si elle a des membreslock()
etunlock()
, vous êtes bon pour aller. Une bonne mise en œuvre decondition_variable_any
nécessite uncondition_variable
membre de données et unshared_ptr<mutex>
membre de données.Parce que cette nouvelle fonctionnalité est plus cher que votre base
condition_variable::wait
, et parce quecondition_variable
de bas niveau de l'outil, très utile, mais plus cher fonctionnalité a été mis dans une classe distincte de sorte que vous ne payez que si vous l'utilisez.lock_guard
, oucondition_variable
, ou peut-êtrecondition_variable::wait
?condition_variable_any
condition_variable::wait
. Oui,condition_variable_any
est le chemin à parcourir. Et la raison que la fonctionnalité n'est pas plié encondition_variable
est qu'il est plus cher. Etcondition_variable
de bas niveau de l'outil, il faut quelque chose qui soit aussi efficace que possible. Vous ne payez que pour les fonctionnalités supplémentaires si vous utilisezcondition_variable_any
.condition_variable_any
avec une plaine de mutex.Il s'agit essentiellement d'une conception d'API décision de faire de l'API la plus sécuritaire possible par défaut (avec la charge supplémentaire d'être considéré comme négligeable). En exigeant de passer un
unique_lock
au lieu d'un rawmutex
les utilisateurs de l'API sont orientés vers l'écriture de code correct (en présence d'exceptions).Au cours des dernières années, l'accent du langage C++ a évolué vers une sécurité par défaut (mais en permettant aux utilisateurs de tirer eux-mêmes leurs pieds s'ils le souhaitent, et essayez assez dur).