74 votes

Comment détecter et de déboguer le multi-threading problèmes?

C'est un suivi de cette question, où je n'avais pas d'obtenir des commentaires sur ce point. Voici la brève question:

Est-il possible de détecter et de déboguer des problèmes à venir de multi-threaded code?

Souvent, nous devons dire à nos clients: "Nous ne pouvons pas reproduire le problème ici, donc nous ne pouvons pas le réparer. Merci de nous indiquer les étapes pour reproduire le problème, nous allons le corriger." C'est en quelque sorte un méchant réponse si je sais que c'est un multi-threading problème, mais surtout je n'en ai pas. Comment puis-je obtenir de savoir qu'un problème est un multi-threading problème et comment le corriger?

Je voudrais savoir si il y a des journalisation des cadres, ou des techniques de débogage, ou code des inspecteurs, ou quoi que ce soit d'autre pour aider à résoudre de tels problèmes. Approches générales sont les bienvenus. Si aucune réponse devrait être liées au langage, puis le garder à .NET et Java.

92voto

Lawrence Dol Points 27976

Threading/les problèmes de simultanéité sont notoirement difficile à reproduire, qui est l'une des raisons pour lesquelles vous devriez conception pour éviter ou au moins minimiser les probabilités. C'est la raison des objets immuables, sont si précieux. Essayez d'isoler les objets mutables à un seul fil, et ensuite soigneusement le contrôle de l'échange d'objets mutables entre les threads. Tenter de programme avec une conception de l'objet en mains, plutôt que de "partagé" des objets. Pour ce dernier, l'utilisation de synchroniser les objets de contrôle (qui sont plus faciles à raison), et éviter d'avoir un objet synchronisé d'utiliser d'autres objets qui doivent également être synchronisés, qui est, essayez de les garder autonome. Votre meilleure défense est une bonne conception.

Les blocages sont le plus facile à déboguer, si vous pouvez obtenir une trace de la pile lors de l'impasse. Compte tenu de la trace, dont la plupart ne détection de blocage, il est facile d'identifier la raison et alors raison à propos du code de pourquoi et de comment le résoudre. Avec les blocages, il va toujours être un problème d'acquérir les mêmes verrous dans des ordres différents.

Vivre les verrous sont plus difficile d'être en mesure d'observer le système, tandis que dans l'état d'erreur est votre meilleur pari là.

Des conditions de course ont tendance à être extrêmement difficile à reproduire, et encore plus difficiles à identifier, à partir de l'analyse manuelle du code. Avec ces derniers, le chemin que j'ai l'habitude de prendre, en plus de nombreux tests à reproduire, est à la raison de ces possibilités, et essayez d'ouvrir une session d'information pour prouver ou réfuter des théories. Si vous avez des preuves directes de la corruption de l'état, vous pourriez être en mesure de raisonner sur les causes possibles basées sur la corruption.

Le plus complexe, le système, plus il est difficile de trouver de la simultanéité des erreurs, et à raison, sur son comportement. Utilisez des outils comme JVisualVM et connexion à distance profileurs - ils peuvent être un épargnant de vie si vous pouvez vous connecter à un système dans un état d'erreur et d'inspecter les fils et les objets.

Aussi, méfiez-vous des différences de comportement qui sont fonction du nombre de cœurs du PROCESSEUR, de pipelines, de la bande passante du bus, etc. Les changements dans le matériel peut affecter votre capacité à reproduire le problème. Certains problèmes ne montrent sur single-core CPU d'autres seulement sur multi-cœurs. Une dernière chose, essayez d'utiliser la simultanéité des objets distribués avec le système de bibliothèques - e.g en Java java.util.simultanées est votre ami. La rédaction de votre propre contrôle de la simultanéité des objets est difficile et lourde de danger; laisser les experts, si vous avez un choix.

7voto

Greg Mattes Points 9578

Je pensais que la réponse que vous avez obtenu à votre autre question a été assez bonne. Mais je vais l'accent sur ces points.

Seulement modifier l'état partagé dans une section critique (Exclusion Mutuelle)

Acquérir des verrous dans un ensemble de commande et de les libérer dans l'ordre inverse.

L'utilisation de pré-construit des abstractions chaque fois que possible (Comme les trucs en java.util.simultanées)

En outre, certains outils d'analyse peut détecter des problèmes potentiels. Par exemple, FindBugs pouvez trouver certains problèmes de threading dans les programmes Java. De tels outils ne trouvez pas tous les problèmes (ils ne sont pas des balles d'argent), mais ils peuvent aider.

Comme vanslly souligne dans un commentaire à cette réponse, en étudiant bien placé en sortie d'enregistrement peut également très utile, mais attention à Heisenbugs.

5voto

krosenvold Points 35979

En supposant que j'ai des rapports sur des problèmes qui sont difficiles à reproduire, je trouve toujours ces par lecture de code, de préférence une paire de code de lecture, de sorte que vous pouvez discuter de filetage sémantique/verrouillage besoins. Lorsque nous faisons cela en fonction sur un problème signalé, je trouve que nous avons toujours des ongles un ou plusieurs problèmes assez rapidement. Je crois aussi que c'est assez bon marché, technique pour résoudre des problèmes difficiles.

Désolé de ne pas être en mesure de dire que vous appuyez sur ctrl+maj+f13, mais je ne pense pas qu'il y a quelque chose comme ce qui est disponible. Mais il suffit de penser au sujet de ce que la question en fait est généralement donne une assez forte sens de l'orientation dans le code, de sorte que vous n'avez pas à démarrer à main().

5voto

mghie Points 25960

En plus de l'autre les bonnes réponses, vous avez déjà obtenu: Toujours tester sur une machine avec au moins autant de processeurs / cœurs de processeur que le client utilise ou qu'il y a des threads dans votre programme. Sinon quelques multithreading bugs peut être difficile, voire impossible à reproduire.

5voto

ChrisW Points 37322

En dehors de crash dumps, une technique est étendue au moment de l'exécution de la journalisation: où chaque thread journaux de ce qu'il fait.

La première question lorsqu'une erreur est signalée, alors, peut-être, "Où est le fichier journal?"

Parfois, vous pouvez voir le problème dans le fichier journal: "Ce fil est la détection d'une illégales/état inattendu ici ... et regardez, cet autre fil a été fait que, juste avant ou juste après cela."

Si le fichier journal ne dit pas ce qui se passe, puis de s'excuser auprès de la clientèle, ajouter suffisamment nombreux journalisation supplémentaire déclarations pour le code, donner le nouveau code pour le client, et de dire que vous allez le fixer après, il arrive une fois de plus.

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