169 votes

Pourquoi pthread_cond_wait a faux réveils ?

Pour citer la page de man:

Lors de l'utilisation de variables de condition, il y a toujours un Booléen prédicat de partager des variables associées à chaque état d'attente qui est vrai si le thread doit procéder. Les réveils intempestifs de la pthread_cond_timedwait() ou pthread_cond_wait() les fonctions peuvent se produire. Depuis le retour de pthread_cond_timedwait() ou pthread_cond_wait() n'implique rien sur la valeur de ce prédicat, le prédicat doit être réévalué à un tel retour.

Donc, pthread_cond_wait pouvez retourner même si vous n'avez pas signalé. À première vue tout au moins, qui semble assez atroce. Ce serait comme une fonction aléatoire retourné la valeur erronée ou de manière aléatoire retourné avant de parvenir à une bonne instruction de retour. Il semble comme un bug majeur. Mais le fait qu'ils ont choisi de ce document dans la page de man plutôt que de fixer, semblerait indiquer qu'il existe un motif légitime pourquoi pthread_cond_wait finit par se réveiller injustifiées. Sans doute, il y a quelque chose d'intrinsèque au sujet de la façon dont il fonctionne, qui fait en sorte que ce ne peut pas être aidé. La question est de savoir quoi.

Pourquoi n' pthread_cond_wait retour faussement? Pourquoi ne peut-il pas vous garantir qu'il va se réveiller quand il a été correctement signalé? Quelqu'un peut-il expliquer la raison de sa fausse comportement?

136voto

acm Points 2906

Il y a au moins deux choses fausses réveil " pourrait signifier:

  • Un thread bloqué dans pthread_cond_wait peuvent renvoyer à partir de l'appeler, même si aucun appel à de signal ou de diffuser sur la condition s'est produite.
  • Un thread bloqué dans pthread_cond_wait retours en raison d'un appel de signal ou de diffusion, cependant, après la ré-le mutex sous-jacents prédicat n'est plus vrai.

Mais ce dernier cas peut se produire même si la variable de condition de mise en œuvre ne permet pas le premier cas. Considérons un producteur consommateur de la file d'attente, et trois fils.

  • Thread 1 a juste retiré un élément et publié le mutex, et la file d'attente est vide. Le thread est en train de faire ce qu'il fait avec l'élément qu'il a acquis sur certains CPU.
  • Thread 2 tente de retirer un élément, mais il trouve que la file d'attente à vide lorsque la case est cochée sous le mutex, les appels pthread_cond_wait, et les blocs de l'appel en attente du signal et de la radiodiffusion.
  • Fil 3 obtient le mutex, insère un nouvel élément dans la file d'attente, informe de la variable de condition, et libère le verrou.
  • En réponse à la notification à partir du fil 3, le thread 2, qui a été en attente sur la condition, est planifiée pour s'exécuter.
  • Cependant, avant que le thread 2 parvient à obtenir sur le CPU et prenez la file d'attente de verrouillage, 1 fil à la fin de la tâche, et renvoie à la file d'attente pour plus de travail. Il obtient la file d'attente de verrouillage, vérifie le prédicat, et constate qu'il y a des travaux dans la file d'attente. Il procède à la résorption de l'élément de fil 3 inséré, libère le verrou, et fait tout ce qu'il fait avec l'élément de fil 3 en file d'attente.
  • Thread 2 obtient sur un PROCESSEUR et obtient le verrou, mais lorsqu'il vérifie le prédicat, il constate que la file d'attente est vide. Thread 1 'volé' de l'élément, de sorte que le réveil semble être faux. Thread 2 doit attendre sur la condition encore.

Donc, puisque vous déjà faut toujours vérifier le prédicat en vertu d'une boucle, il ne fait aucune différence si la condition sous-jacente variables peuvent avoir d'autres sortes de parasites de réveils.

83voto

NPE Points 169956

L'explication suivante est donnée par David R. Butenhof dans "Programmation avec des Threads POSIX" (p. 80):

Les réveils intempestifs peut sembler étrange, mais sur certains systèmes multiprocesseurs, faisant état de réveil complètement prévisible pourrait freiner considérablement toutes les opérations de variable de condition.

Dans la suite de la comp.de la programmation.les threads de discussion, il développe le raisonnement à la base de la conception:

Patrick Doyle a écrit: 
> Dans l'article , Tom Payne a écrit: 
> >Kaz Kylheku a écrit: 
> >: Il en est ainsi parce que les implémentations peuvent parfois ne pas éviter l'insertion de 
> >: ces fausses réveils; il pourrait être coûteux pour les prévenir. 

> >Mais pourquoi? Pourquoi est-ce si difficile? Par exemple, nous parlons de 
> >les situations où un temps d'attente d'un signal arrive? 

> Vous savez, je me demande si les concepteurs de pthreads utilisé la logique comme ceci: 
> les utilisateurs de variables de condition pour vérifier l'état à la sortie, de toute façon, 
> afin de ne pas imposer de charge supplémentaire sur eux si nous permettons à 
> fausse réveils; et depuis il est concevable qu'en permettant à des parasites 
> réveils pourrait apporter une mise en œuvre plus rapide, il ne peut aider si nous 
> le leur permettent. 

> Ils ne peuvent pas avoir eu une mise en oeuvre particulière à l'esprit. 

Vous êtes effectivement pas loin du tout, sauf que vous n'avez pas poussé assez loin. 

L'intention était de le forcer à corriger/robuste code en exigeant prédicat boucles. C'était 
poussé par la prouvable de corriger académique contingent parmi les "core threadies" 
le groupe de travail, bien que je ne pense pas que quiconque vraiment en désaccord avec l'intention 
une fois qu'ils ont compris ce que cela signifiait. 

Nous avons suivi cette intention avec plusieurs niveaux de justification. La première est que les 
"religieusement" à l'aide d'une boucle protège la demande à l'encontre de ses propres imparfaite 
pratiques de codage. La seconde était qu'il n'était pas difficile à imaginer de façon abstraite 
machines et la mise en œuvre du code qui pourrait exploiter cette obligation d'améliorer les 
le rendement de la moyenne de l'état des opérations d'attente grâce à l'optimisation de la 
la synchronisation des mécanismes. 
/------------------[ David.Buten...@compaq.com ]------------------\ 
| Compaq Computer Corporation POSIX Thread Architecte | 
| Mon livre: http://www.awl.com/cseng/titles/0-201-63392-2/ | 
\-----[ http://home.earthlink.net/~anneart/family/dave.html ]-----/ 

7voto

Jingguo Yao Points 513

La section « Réveils multiples par Signal de Condition » dans pthread_cond_signal contient un exemple d’implémentation de pthread_cond_wait et pthread_cond_signal qui implique de wakekups parasites.

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