Pour citer la page de manuel:
Lorsque vous utilisez des variables de condition, il existe toujours un prédicat booléen impliquant des variables partagées associées à chaque condition d'attente qui est vrai si le thread doit continuer. Des réveils parasites des fonctions pthread_cond_timedwait () ou pthread_cond_wait () peuvent se produire. Comme 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é lors de ce retour.
Alors, pthread_cond_wait
peut revenir même si vous ne l'avez pas signalé. À première vue du moins, cela semble assez atroce. Ce serait comme une fonction qui a renvoyé au hasard la mauvaise valeur ou retournée au hasard avant qu'elle n'atteigne réellement une instruction de retour appropriée. Cela semble être un bug majeur. Mais le fait qu'ils aient choisi de documenter cela dans la page de manuel plutôt que de le corriger semble indiquer qu'il existe une raison légitime pour laquelle pthread_cond_wait
finit par se réveiller faussement. Vraisemblablement, il y a quelque chose d'intrinsèque dans la façon dont cela fonctionne qui fait que cela ne peut pas être aidé. La question est quoi.
Pourquoi fait pthread_cond_wait
rentrer faux? Pourquoi ne peut-il pas garantir qu'il ne se réveillera que lorsqu'il aura été correctement signalé? Quelqu'un peut-il expliquer la raison de son comportement fallacieux?
L'explication suivante est donnée par David R. Butenhof dans "Programmation avec des threads POSIX" (p. 80):
Des réveils parasites peuvent sembler étranges, mais sur certains systèmes multiprocesseurs, rendre le réveil des conditions complètement prévisible peut ralentir considérablement toutes les opérations de variables de conditions.
Dans ce qui suit discussion comp.programming.threads , il développe la réflexion derrière la conception:
Patrick Doyle a écrit: > Dans l'article, Tom Payne a écrit: >> Kaz Kylheku a écrit: >>: C'est parce que les implémentations ne peuvent parfois pas éviter insérer >>: ces faux réveils; il pourrait être coûteux de les empêcher. >> Mais pourquoi? Pourquoi est-ce si difficile? Par exemple, parlons-nous de >> Situations où une attente expire au moment où un signal arrive? > Vous savez, je me demande si les concepteurs de pthreads ont utilisé une logique comme celle-ci: > Les utilisateurs des variables de condition doivent quand même vérifier la condition à la sortie, > nous ne leur imposerons donc aucun fardeau supplémentaire si nous autorisons > réveils parasites; et comme il est concevable que l’autorisation de > réveils parasites puisse accélérer la mise en œuvre, cela ne peut aider que si nous > les autorisons. > Ils n'avaient peut-être pas en tête d'implémentation particulière. Vous n'êtes en fait pas loin du tout, sauf que vous n'avez pas poussé assez loin. L'intention était de forcer le code correct/robuste en exigeant des boucles de prédicat. Ceci était Motivé par le contingent académique prouvablement correct parmi les "sujets centraux" du Groupe de travail, bien que je ne pense pas que quiconque soit 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. Le premier était que "Religieusement" en utilisant une boucle protège l'application contre ses propres pratiques de codage Imparfaites. La seconde était qu'il n'était pas difficile d'imaginer de manière abstraite Machines et code d'implémentation qui pourraient exploiter cette exigence pour améliorer La performance des opérations d'attente de condition moyenne en optimisant les mécanismes de synchronisation . /------------------ [David.Buten ... @ compaq.com] -------------- ----\ | Compaq Computer Corporation Architecte de thread POSIX | | Mon livre: http://www.awl.com/cseng/titles/0-201-63392-2/ | \----- [http://home.earthlink.net/~anneart/family/dave.html] -----/
Il y a au moins deux choses qu'un "réveil fallacieux" pourrait signifier:
pthread_cond_wait
peut revenir de l'appel même si aucun appel n'a été signalé ou diffusé à la condition.pthread_cond_wait
renvoie en raison d'un appel à signaler ou à diffuser, mais après avoir acquis de nouveau le mutex, le prédicat sous-jacent n'est plus vrai.Mais le dernier cas peut se produire même si l'implémentation de la variable de condition ne permet pas le premier cas. Prenons une file d'attente de consommateurs producteurs et trois threads.
pthread_cond_wait
et bloque l'appel en attente de signal/diffusion.Donc, comme vous devez déjà toujours vérifier le prédicat sous une boucle, cela ne fait aucune différence si les variables de condition sous-jacentes peuvent avoir d'autres sortes de réveils parasites.
La section "Réveils multiples par signal de condition" dans pthread_cond_signal a un exemple d'implémentation de pthread_cond_wait et pthread_cond_signal qui implique des réveils parasites.