Comment puis-je attendre qu'un fil détaché ait fini en C ++?
Je m'en fiche d'un statut de sortie, je veux juste savoir si le fil est terminé ou non. P>
i 'm Essayez de fournir une enveloppe synchrone autour d'un outil de Tirebroyarty asynchrone. Le problème est un accident de la condition de course étrange impliquant un rappel. La progression est: p>
Je veux envelopper cela dans un mécanisme qui fournit un appel de blocage. Jusqu'à présent, j'ai: p> aussi loin que possible, cela devrait fonctionner, et cela le fait généralement, mais il se bloque parfois. Autant que je puisse déterminer du centre-virgule, je suppose que ceci: p> J'ai essayé beaucoup de mécanismes différents pour essayer de résoudre ce problème, mais aucun d'entre eux ne résout le problème. Je vois toujours des accidents occasionnels. P> Cela fait partie d'une application massivement multithreadée, la création d'une attente statique n'est donc pas pratique. . P> J'ai dirigé un test, créant une attente sur le tas et fuit délibérément la mémoire (c'est-à-dire que les objets d'attente ne sont jamais traités), et cela n'en a entraîné aucun crash. Donc, je suis sûr que c'est un problème d'attente d'être distribué trop tôt. P> J'ai également essayé un test avec un Je ne pensais pas que c'était pertinent au début, mais le Plus j'en pense, plus je pense que c'est le vrai problème: p> Les trucs de troisième partie que j'ai mentionnés et pourquoi je n'ai aucun contrôle sur le fil: Ceci utilise Corba. P> Donc, il est possible que Corba se tienne une référence à mon objet plus longtemps que prévu. P> P>
Sleep (5) code> après le déverrouillage dans
attendre code>, et cela n'a également produit aucun crash. Je déteste compter sur un kludge comme ça. P>
4 Réponses :
Oui, je crois que ce que vous décrivez, c'est ce qui se passe (condition de race sur Deallocate). Un moyen rapide de résoudre ce problème est de créer une instance statique d'attente, qui ne sera pas détruite. Cela fonctionnera aussi longtemps que vous n'avez pas besoin d'avoir plus d'un serveur en même temps. P>
Vous utiliserez également de manière permanente cette mémoire, elle ne sera pas contraignante. Mais ça ne semble pas trop mal. P>
Le problème principal est qu'il est difficile de coordonner la durée de vie de vos constructions de communication de fil entre les threads: vous aurez toujours besoin d'au moins une construction de communication de rallonges pour communiquer lorsqu'il est sûr de détruire (au moins dans des langues sans collection de déchets, comme C ++. ). p>
EDIT STRUT>: Voir les commentaires pour quelques idées sur refcountating avec un mutex global. P>
Malheureusement, c'est dans une application massivement multithreadée, et nous voulons vraiment des objets d'attente séparés pour chacun - sinon cela nous ralentit trop.
De plus, si nous utilisons une attente statique, il y a le problème d'essayer de coordonner quel fil doit reprendre le fil.
Ok, tu peux faire ça. Vous pouvez ajouter un champ Refcount à l'objet d'attente, protégé par un mutex global. Commencez le Refcount à 2, puis avez le rappel et le serveur décrémentez les deux refcount lorsque vous avez terminé. Si le mutex mondial devient votre goulot d'étranglement, il existe d'autres solutions plus compliquées.
De plus, vous n'avez pas besoin du mutex global si vous pouvez utiliser des opérations atomiques pour le réfCount.
Excellent! Le refCounting est en fait fourni par Corba, mais cela a résolu le problème! Merci!
Au meilleur de ma connaissance, il n'y a pas de moyen portable de demander directement à un thread si c'est fait en cours d'exécution (c'est-à-dire non pthread _ code> fonction). Ce que vous faites est em> la bonne façon de le faire, au moins jusqu'à avoir une condition que vous signalez. Si vous voyez des accidents que vous assurez que vous êtes sûr due à l'objet code> WAIT code> est utilisé lorsque le fil qui le crée a quitté (et non quelques autres em> problème de verrouillage subtil - tout Trop commun), le problème est que vous devez vous assurer que le
attendre code> n'est pas em> étant distribué, en gérant à partir d'un fil autre que celui qui fait la notification. Mettez-le dans la mémoire globale ou allouez de manière dynamique et partagez-la avec ce fil. Il ne suffit tout simplement pas de ne pas avoir le fil attendu seul la mémoire de l'attente, faites le fil de l'attente. P>
Est-ce que vous initialisez et détruisez-vous correctement le mutex et la condition Var correctement?
Wait::Wait() { pthread_mutex_init(&m_mutex, NULL); pthread_cond_init(&m_cond, NULL); m_done = false; } Wait::~Wait() { assert(m_done); pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&m_cond); }
Oui, le mutex etond sont initialisés / détruits correctement. J'utilise en fait des cours d'emballage sur ceux qui ont été bien testés. Et oui, je suis certain que l'attente est détruite prématurément - tandis qu'un fil est toujours à attendre :: rappel.
Si votre hypothèse est correcte, le module tiers semble être buggy et vous devez proposer une sorte de hack pour faire fonctionner votre candidature. P>
statique Disclaimer: Je ne suis en aucun cas un expert en sécurité du fil, alors considérez ce post comme une suggestion d'un profane. P> attendre code> n'est pas réalisable. Que diriez-vous de
attendre code> piscine (elle peut même augmenter à la demande)? Votre application utilise-t-elle la piscine de thread pour exécuter?
Bien qu'il y ait toujours une chance que le même
attendre code> soit réutilisé tandis que le module tiers l'utilise toujours. Mais vous pouvez minimiser ces chances en traitant correctement les attentes vacantes dans votre piscine. P>