pthreads : pthread_cond_signal() dans la section critique
J'ai le morceau de code suivant dans Un thread, ce qui bloque l'utilisation de pthread_cond_wait()
pthread_mutex_lock(&my_lock);
if ( false == testCondition )
pthread_cond_wait(&my_wait,&my_lock);
pthread_mutex_unlock(&my_lock);
J'ai le morceau de code suivant dans le fil B, qui signale Un thread
pthread_mutex_lock(&my_lock);
testCondition = true;
pthread_cond_signal(&my_wait);
pthread_mutex_unlock(&my_lock);
Il n'existe pas d'autres fils, serait-il une différence si pthread_cond_signal(&my_wait)
est déplacé hors de la section critique bloc comme indiqué ci-dessous ?
pthread_mutex_lock(&my_lock);
testCondition = true;
pthread_mutex_unlock(&my_lock);
pthread_cond_signal(&my_wait);
OriginalL'auteur curryage | 2009-10-28
Vous devez vous connecter pour publier un commentaire.
Ma recommandation est généralement de garder le
pthread_cond_signal()
appeler à l'intérieur de la région verrouillée, mais probablement pas pour les raisons que vous pensez.Dans la plupart des cas, il n'a pas vraiment d'importance si vous appelez
pthread_cond_signal()
avec la serrure lieu ou non. Ben est juste que certains planificateurs peuvent forcer un changement de contexte lorsque le verrou est libéré s'il y a un autre thread en attente, de sorte que votre fil peut être mis à l'écart avant d'appelerpthread_cond_signal()
. D'autre part, certains planificateurs va exécuter le thread en attente dès que vous appelezpthread_cond_signal()
, donc si vous l'appelez avec le verrou, le thread en attente va se réveiller et puis se remettre à dormir (parce que c'est maintenant bloqué sur le mutex) jusqu'à ce que la signalisation thread il se déverrouille. Le comportement exact est très spécifique à l'implémentation et peuvent changer entre les versions de système d'exploitation, de sorte qu'il n'y a rien que vous pouvez compter sur.Mais, tout cela ressemble-delà de ce que doit être votre principale préoccupation, qui est la lisibilité et l'exactitude de votre code. Vous n'êtes pas susceptible de voir tout le monde réel avantage en matière de performances de ce type de micro-optimisation (rappelez-vous la règle d'optimisation: profil d'abord, optimiser la deuxième). Cependant, il est plus facile de penser que le flux de contrôle si vous savez que l'ensemble des threads en attente ne peut pas changer entre le moment où vous définissez la condition et envoyer le signal. Sinon, vous devez penser à des choses telles que "si le thread A jeux de
testCondition=TRUE
et libère le verrou, puis le fil B s'exécute et voit quetestCondition
est vrai, alors il saute lepthread_cond_wait()
et passe pour réinitialisertestCondition
àFALSE
, puis enfin Un thread s'exécute et appelspthread_cond_signal()
, qui réveille le thread C parce que le thread B n'est pas vraiment d'attente, maistestCondition
n'est pas vrai". Ceci est source de confusion et peut conduire à de difficiles à diagnostiquer des conditions de course dans votre code. Pour cette raison, je pense que c'est mieux de signal avec le verrou; de cette façon, vous savez que la définition de la condition et de l'envoi d'un signal sont atomiques à l'égard les uns des autres.Sur une note connexe, la façon dont vous appelez
pthread_cond_wait()
est incorrect. Il est possible (mais rare) pourpthread_cond_wait()
de revenir sans la variable de condition fait d'être signalée, et il y a d'autres cas (par exemple, la course, j'ai décrit ci-dessus) où un signal pourrait éveiller un thread, même si la condition n'est pas vrai. Pour être sûr, vous avez besoin de mettre lapthread_cond_wait()
appel à l'intérieur d'unwhile()
boucle qui teste la condition, de sorte que vous appeler enpthread_cond_wait()
si la condition n'est pas satisfaite après vous acquérir le verrou. Dans votre exemple, il devrait ressembler à ceci:(J'ai aussi corrigé ce qui était probablement une faute de frappe dans votre exemple d'origine, qui est de l'utilisation de
my_mutex
pour lapthread_cond_wait()
appel, au lieu demy_lock
.)pthread_cond_signal()
/pthread_cond_broadcast()
signifie: j'ai fait de mon travail sur la section critique, vous, les autres threads, pouvez ramasser ce que j'ai préparé pour vous - c'est peut-être le transfert de données, ou d'espace pour écrire de nouvelles données, ou tout autre type de ressource. Pourquoi, donc, d'en informer les autres threads qui ils peuvent travailler, s'ils ne le peuvent pas?OriginalL'auteur Marc Unangst
Le thread en attente sur la variable de condition doit garder le mutex verrouillé, et l'autre thread doit toujours signal avec le mutex est verrouillé. De cette façon, vous savoir l'autre thread est en attente sur la condition lorsque vous envoyez le signal. Sinon, il est possible que le thread en attente ne verrez pas la condition d'être signalée et bloquer indéfiniment en attente.
Les variables de Condition sont généralement utilisés comme ceci:
C'est valide:
Cependant, considérer ce qui se passe dans
main
Si le retard est décrit par ce commentaire qui se passe,
pthread_cond_wait
seront laissées en attente—peut-être pour toujours. C'est pourquoi vous voulez signal avec le mutex est verrouillé.go
ici).Même si dans votre exemple de la 1ère version que vous mettiez l'appel à
pthread_cond_signal()
à l'extérieur de la critcal section protégée par le mutex n course allait être exécuté, etmain()
ne serait jamais coincé.OriginalL'auteur LnxPrgr3
Les deux sont corrects, mais pour la réactivité des questions, la plupart des planificateurs de donner la main à un autre thread lorsqu'un verrou est libéré. Je vous n'avez pas de signal avant de déverrouillage, votre thread en attente d'Une n'est pas dans la liste et thous ne seront pas programmées jusqu'à ce que B est à nouveau prévues et appel pthread_cond_signal().
OriginalL'auteur Ben
La Groupe ouvert de la Base de Spécifications Numéro 7 de la norme IEEE Std 1003.1, Édition 2013 (qui, autant que je peux dire c'est officiel pthread spécification) affirme à ce sujet:
Pour ajouter mon expérience personnelle, je travaille sur une application qui a de code où la variable de condition a été détruit (et de la mémoire contenant libéré) par le thread qui a été réveillé. Nous avons constaté que sur un multi-appareil de base (un iPad Air 2) le pthread_cond_signal() pourrait en fait crash parfois si elle était en dehors de la mutex lock, comme le garçon s'est réveillé et a détruit la variable de condition avant le pthread_cond_signal avait terminé. C'était tout à fait inattendu.
Je voudrais donc certainement tourner vers le signal de l'intérieur de la serrure " version, il semble être plus sûr.
OriginalL'auteur JosephH
Ici est belle écriture sur les variables conditionnelles: Techniques pour Améliorer l'Évolutivité des Applications à l'Aide des Threads POSIX Variables de Condition (voir sous "comment Éviter le Mutex de Contention" de la section et du point 7)
Il est dit que, la deuxième version peut avoir certains avantages de performance. Parce qu'il rend possible pour le thread avec pthread_cond_wait attendre moins fréquemment.
OriginalL'auteur kokosing