Étant donné un extrait de code suivant (trouvé dans quelque part tout en apprenant le filetage).
if(queue.Count == 0) Monitor.Wait(sync);
5 Réponses :
Vous devez vérifier si la file d'attente est toujours vide ou non. En utilisant uniquement si vous ne le vérifieriez qu'une seule fois, attendez un moment, puis une déléue. Et si à ce moment-là, la file d'attente est toujours vide? CLAQUER! Erreur de sous-ensemise de la file d'attente ... P>
Mais une attente ne se réveille que après une impulsion, et cela arrive quand quelque chose est en cours.
avec si strong> condition quand quelque chose a libéré le verrouillage de la queue
if (queue.Count == 0) will do.Using while loop pattern for "wait for and check condition" context is a legacy leftover, I think. Because non-Windows, non-.NET monitor variables can be triggered without actual Pulse.In .NET, you private monitor variable cannot be triggered without Queue filling so you don't need to worry about queue underflow after monitor waiting. But, it is really not bad habit to use while loop for "wait for and check condition".
Cela me semble très complexe, pouvez-vous indiquer une ressource sur laquelle je peux comprendre ce que vous voulez dire.
Eh bien .. j'ai bien peur de ne pas pouvoir fournir une ressource plus détaillée à ce sujet. Cela vient de ma propre expérience. J'ai utilisé 'si ..' coding de nombreuses années sous Windows et n'avait aucun problème. Quand j'ai utilisé 'si ..' coding à Linux? tous foirés. Vous devez utiliser la boucle pour les variables de moniteur (condition) dans la plate-forme * Nix. Après cela, j'utilise toujours tout en boucle quelle que soit la langue / la plate-forme.
IMHO Un simple si code> ne fera pas. Vous pouvez rencontrer une condition de course si un autre thread
délesille code> entre-temps. Je soupçonne que cela dépend si
pulseall code> ou juste
impulsion code> est appelé ...
Même si impulsion code> a été utilisé, il y aurait toujours un problème avec le simple
si code> chèque.
Les threads multiples ne peuvent pas exécuter «si ...» du code en raison de la déclaration de verrouillage précédent (Sync).
Vous devez comprendre ce que Sur la base de ces connaissances, il est assez facile de comprendre pourquoi vous devez revérifier le décompte de la file d'attente lorsque vous utilisez Alors, quelle serait la conclusion si vous aviez utilisé Le La meilleure règle de base ici est que s'il y a un doute sur l'utilisation d'un pulse code>,
pulseall code> et
attendre code> fait. Le moniteur
code> maintient deux files d'attente: la file d'attente d'attente et la file d'attente Ready. Lorsqu'un fil d'appels
attend code> il est déplacé dans la file d'attente d'attente. Lorsqu'un fil appelle
impulsion code> Il déplace un et un seul fil em> de la file d'attente en attente à la file d'attente Ready. Lorsqu'un filetage appelle
pulseall code> il déplace tous les discussions em> de la file d'attente en attente à la file d'attente Ready. Les fils dans la file d'attente Ready sont éligibles pour réacquérir la serrure à tout moment, mais seulement après la libération du détenteur actuel. P>
pulseall code>. C'est parce que tous em> de threads de déquenseur sera éventuellement réveillez-vous et voudra essayer d'extraire un élément de la file d'attente. Mais, si s'il n'y a qu'un seul article dans la file d'attente pour commencer? Évidemment, nous devons revérifier le nombre de file d'attente pour éviter de déroger une file d'attente vide. P>
pulse code> au lieu de
pulseall code>? Il y aurait toujours un problème avec le simple
si code> chèque. La raison en est que le thread de la file d'attente Ready ne sera pas nécessairement le prochain thread pour acquérir la serrure. C'est-à-dire que le moniteur
code> ne donne pas de préférence à un
attendre code> appel au-dessus d'un
entrée code> appel. P>
pendant code> est un motif assez standard lors de l'utilisation de
moniteur.Wait code>. C'est parce que pulsant un fil n'a pas de sens sémantique par lui-même. Ce n'est qu'un signal que l'état de verrouillage a changé. Lorsque les threads se réveillent après avoir bloqué sur
attendre code> ils doivent revendre la même condition utilisée à l'origine pour bloquer le thread pour voir si le thread peut maintenant procéder. Parfois, il ne peut pas et il devrait donc bloquer un peu plus. P>
si code> vérifier ou un
lors de la vérification code> alors choisissez toujours un
pendant code> boucle parce qu'il est plus sûr. En fait, je prendrais cela à l'extrême et suggérez à toujours em> utiliser un
pendant que code> car il n'y a pas d'avantage inhérent à l'utilisation du plus simple
si code> Vérifier et parce que le contrôle
si code> est presque toujours le mauvais choix de toute façon. Une règle similaire contient pour choisir s'il faut utiliser
impulsion code> ou
pulseall code>. S'il y a un doute sur lequel utiliser alors toujours choisir
pulseall code>. P>
+1 Guide très utile sur l'utilisation du moniteur. En effet, «si» sans double verrouillage n'est rien d'autre qu'un désastre de débogage.
@Brain Gideon. Explication géniale!
Ne pensez-vous pas que le moniteur .NET est imparfait dans la conception? Il ne devrait pas y avoir que deux files d'attente; Il devrait y avoir plus d'une file d'attente en attente, chacune pour une condition d'attente particulière spécifiée par la paire de la variable
@ H9UEST: Vous faites un bon point. Je ne sais pas si j'irais aussi loin que de dire que c'est un défaut, mais il y a définitivement des inconvénients avec le design actuel. Pourrait-il être meilleur? Probablement ... oui, mais à quel coût?
Pourquoi sur UNIX, cela pourrait aller mal, c'est due au réveil parasite, possibilité causée par des signaux de système d'exploitation. C'est un effet secondaire qui n'est pas garanti de ne jamais arriver sous Windows également. Ce n'est pas un héritage, c'est la façon dont OS fonctionne. Si les moniteurs sont mis en œuvre en termes de variable de condition, c'est-à-dire. P>
DEF: A Eassious Wake Up em> est une nouvelle planification d'un fil de couchage sur un site d'attente variable de condition, qui n'a pas été déclenché par une action provenant des threads de programme actuels (comme Ce désagrément pourrait être masqué dans des langues gérées par exemple. les files d'attente. Donc, avant de sortir de la fonction PULSE () CODE>). P>
wait () code>, le cadre peut vérifier que ce thread en cours d'exécution est réellement demandé pour la planification, si cela ne se trouve pas dans une file d'attente d'exécution, elle peut revenir au sommeil. . Cacher le problème. P>
Vous voudrez peut-être spécifier la langue et ajouter une balise appropriée.
J'ai oublié que quelqu'un a déjà ajouté c # tag.
C'est à voir avec la sémantique Hoare contre Sémantique Mesa [Schedulting Mesa]. En général, vous devez utiliser des boucles avec la planification de MESA. Mais dans votre cas particulier, cela n'aurait pas d'importance.