Question

J'ai trouvé cet intéressant paragraphe dans le Documentation sur les threads Boost :

void wait(boost::unique_lock<boost::mutex>& lock)

...

  

Effets: appelez atomiquement lock.unlock ()   et bloque le thread actuel. le   le fil se débloquera à la réception d'un message   appeler this- > notify_one () ou   this- > notify_all () ou de manière fausse .   Lorsque le fil est débloqué (pour   quelle que soit la raison), le verrou est   ré-acquis en appelant lock.lock ()   avant que l'appel à attendre revienne. le   le verrou est également ré-acquis en appelant   lock.lock () si la fonction se termine avec   une exception.

Donc, ce qui m'intéresse, c'est la signification du mot "de manière fausse". Pourquoi le fil serait-il débloqué pour des raisons fallacieuses? Que peut-on faire pour résoudre ce problème?

Était-ce utile?

La solution

Cet article de Anthony Williams est particulièrement détaillé. .

  

Des sillages parasites ne peuvent être prédits:   ils sont essentiellement aléatoires de la   point de vue de l'utilisateur. Cependant, ils   se produisent généralement lorsque la bibliothèque de thread   ne peut pas assurer de manière fiable qu'une attente   thread ne manquera pas une notification.   Depuis une notification manquée serait   rendre la variable de condition inutile,   la bibliothèque de threads réveille le thread   de son attente plutôt que de prendre la   risque.

Il souligne également que vous ne devez pas utiliser les surcharges timed_wait qui prennent une durée, et que vous devez généralement utiliser les versions utilisant un prédicat

.
  

C'est le bogue du débutant, et un   c'est facilement surmonté avec un simple   règle: vérifiez toujours votre prédicat dans un   boucle en attente avec une condition   variable. Le bogue le plus insidieux vient   de timed_wait ().

Cet article de Vladimir Prus est également intéressant.

  

Mais pourquoi avons-nous besoin de la boucle while,   ne pouvons-nous pas écrire:

if (!something_happened)
  c.wait(m);
  

Nous ne pouvons pas. Et la raison meurtrière est que "attendre" peut   revenir sans aucun appel 'notifier'.   Cela s'appelle le réveil parasite et est   explicitement autorisé par POSIX.   Essentiellement, revenir de 'attendre' seulement   indique que les données partagées peuvent   ont changé, de sorte que les données doivent être   évalué à nouveau.

     

D'accord, alors pourquoi cela n'est-il pas encore résolu?   La première raison est que personne ne veut   réparer. Appel enveloppant à 'attendre' dans   une boucle est très souhaitée pour plusieurs   autres raisons. Mais ces raisons   nécessite une explication, bien que fausse   le réveil est un marteau qui peut être appliqué   à tout étudiant de première année sans   échouer.

Autres conseils

Ce billet de blog donne une raison pour Linux, en termes de l'appel système futex renvoyé lorsqu'un signal est transmis à un processus. Malheureusement, cela n'explique rien d'autre (et demande en effet plus d'informations).

La entrée de Wikipedia sur les fausses wakeups (qui semble être un concept à l'échelle de posix, btw, ne se limite pas à augmenter) peut également vous intéresser.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top