2009-01-31 9 views
54

यह this question का अनुवर्ती है, जहां मुझे इस बिंदु पर कोई इनपुट नहीं मिला। यहां संक्षिप्त प्रश्न है:बहु-थ्रेडिंग समस्याओं का पता लगाने और डिबग कैसे करें?

क्या बहु-थ्रेडेड कोड से आने वाली समस्याओं का पता लगाना और डीबग करना संभव है?

अक्सर हमें अपने ग्राहकों को यह बताने पड़ते हैं: "हम यहां समस्या को पुन: पेश नहीं कर सकते हैं, इसलिए हम इसे ठीक नहीं कर सकते हैं। कृपया हमें समस्या को पुन: उत्पन्न करने के लिए कदम बताएं, फिर हम इसे ठीक कर देंगे।" यह किसी भी तरह का बुरा जवाब है अगर मुझे पता है कि यह एक बहु थ्रेडिंग समस्या है, लेकिन ज्यादातर मैं नहीं करता हूं। मुझे यह कैसे पता चलेगा कि एक समस्या एक बहु थ्रेडिंग समस्या है और इसे कैसे डिबग करना है?

मैं जानना चाहता हूं कि कोई विशेष लॉगिंग फ्रेमवर्क, या डिबगिंग तकनीक, या कोड इंस्पेक्टर, या ऐसे मुद्दों को हल करने में मदद के लिए कुछ और है या नहीं। सामान्य दृष्टिकोण स्वागत है। यदि कोई उत्तर भाषा से संबंधित होना चाहिए तो इसे .NET और Java पर रखें।

उत्तर

68

थ्रेडिंग/समवर्ती समस्याएं प्रतिकृति के लिए कुख्यात रूप से मुश्किल हैं - जो कारणों से बचने या कम से कम कम से कम कम करने के कारणों में से एक है। यही कारण है कि अपरिवर्तनीय वस्तुएं इतनी मूल्यवान हैं। एक एकल धागे में परिवर्तनीय वस्तुओं को अलग करने की कोशिश करें, और फिर थ्रेड के बीच परिवर्तनीय वस्तुओं के आदान-प्रदान को ध्यान से नियंत्रित करें। "साझा" ऑब्जेक्ट्स के बजाए ऑब्जेक्ट हैंड-ओवर के साथ प्रोग्राम करने का प्रयास करें। उत्तरार्द्ध के लिए, पूरी तरह से सिंक्रनाइज़ किए गए नियंत्रण ऑब्जेक्ट्स (जो कि कारणों के लिए आसान हैं) का उपयोग करें, और सिंक्रनाइज़ ऑब्जेक्ट को अन्य ऑब्जेक्ट्स का उपयोग करने से बचें जिन्हें सिंक्रनाइज़ किया जाना चाहिए - यानी, उन्हें स्वयं निहित रखने की कोशिश करें। आपका सबसे अच्छा बचाव एक अच्छा डिजाइन है।

डेडलॉक्स डीबग करने के लिए सबसे आसान हैं, अगर आप डेडलॉक करते समय स्टैक ट्रेस प्राप्त कर सकते हैं। ट्रेस को देखते हुए, जिनमें से अधिकांश डेडलॉक पहचान करते हैं, कारण को इंगित करना आसान है और फिर कोड के बारे में कारण यह है कि इसे क्यों और कैसे ठीक किया जाए। Deadlocks के साथ, यह हमेशा विभिन्न आदेशों में एक ही ताले हासिल करने में एक समस्या होने जा रहा है।

लाइव ताले कठिन हैं - त्रुटि स्थिति में सिस्टम का निरीक्षण करने में सक्षम होने पर आपकी सबसे अच्छी शर्त है।

रेस की स्थिति प्रतिकृति के लिए बेहद मुश्किल हो रही है, और मैन्युअल कोड समीक्षा से पहचानना भी मुश्किल है। इनके साथ, जिस मार्ग को मैं आमतौर पर लेता हूं, प्रतिकृति के लिए व्यापक परीक्षण के अलावा, संभावनाओं के बारे में कारण है, और सिद्धांतों को साबित करने या अस्वीकार करने के लिए जानकारी लॉग करने का प्रयास करना है। यदि आपके पास राज्य भ्रष्टाचार का प्रत्यक्ष सबूत है तो आप भ्रष्टाचार के आधार पर संभावित कारणों के बारे में सोच सकते हैं।

सिस्टम जितना जटिल होगा, कंसूरेंसी त्रुटियों को ढूंढना कठिन होगा, और इसके व्यवहार के बारे में कारण होगा। JVisualVM और रिमोट कनेक्ट प्रोफाइलर्स जैसे टूल का उपयोग करें - यदि आप किसी त्रुटि स्थिति में किसी सिस्टम से कनेक्ट कर सकते हैं और थ्रेड और ऑब्जेक्ट का निरीक्षण कर सकते हैं तो वे जीवन बचतकर्ता हो सकते हैं।

इसके अलावा, संभावित व्यवहार में मतभेदों से सावधान रहें जो सीपीयू कोर, पाइपलाइनों, बस बैंडविड्थ आदि की संख्या पर निर्भर हैं। हार्डवेयर में परिवर्तन समस्या को दोहराने की आपकी क्षमता को प्रभावित कर सकते हैं। कुछ समस्याएं केवल एकल-कोर CPU पर दूसरों को बहु-कोर पर दिखाएंगी।

एक आखिरी बात, सिस्टम पुस्तकालयों के साथ वितरित समवर्ती वस्तुओं का उपयोग करने का प्रयास करें - उदाहरण के लिए जावा java.util.concurrent में आपका मित्र है। अपनी खुद की समवर्ती नियंत्रण वस्तुओं को लिखना कठिन और खतरे से भरा हुआ है; यदि आपके पास कोई विकल्प है, तो इसे विशेषज्ञों को छोड़ दें।

+4

ऐसे उपकरण हैं जो रेस की स्थिति का पता लगा सकते हैं। .NET के लिए आप माइक्रोसॉफ्ट द्वारा [CHESS] (http://research.microsoft.com/en-us/projects/chess/) पर एक नज़र डाल सकते हैं जो प्रत्येक संभावित इंटरलीविंग के लिए कोड चलाकर दौड़ की स्थिति का पता लगाने का प्रयास करता है। जावा के लिए आप [थ्रेडसेफ] (http://www.contemplateltd.com/threadsafe) प्राप्त कर सकते हैं जो विशेष रूप से समवर्ती बग का पता लगाने और डिबग करने के लिए एक उपकरण है। –

+0

FindBugs संभावित थ्रेडिंग त्रुटियों को ढूंढने के लिए एक अच्छा स्थिर विश्लेषण टूल भी है। –

7

मैंने सोचा कि answer आपको other question बहुत अच्छा था। लेकिन मैं इन बिंदुओं पर जोर दूंगा।

केवल एक महत्वपूर्ण अनुभाग में साझा किए राज्य को संशोधित (म्युचुअल बहिष्करण) एक सेट क्रम में

मोल ताले और उन्हें विपरीत क्रम में छोड़ दें। पूर्व-निर्मित कपोल-कल्पना

उपयोग जब भी संभव हो (java.util.concurrent में सामान की तरह)

इसके अलावा, कुछ विश्लेषण उपकरणों कुछ संभावित मुद्दे की पहचान कर सकते हैं। उदाहरण के लिए, FindBugs जावा प्रोग्राम में कुछ थ्रेडिंग समस्याएं पा सकते हैं। ऐसे उपकरण सभी समस्याओं को नहीं ढूंढ सकते हैं (वे चांदी की गोलियाँ नहीं हैं) लेकिन वे मदद कर सकते हैं।

vanslly इस उत्तर पर एक टिप्पणी में बताए गए, अच्छी तरह से लॉगिंग आउटपुट का अध्ययन करना भी बहुत उपयोगी हो सकता है, लेकिन Heisenbugs से सावधान रहें।

+0

के बारे में गलत राज्य या अपवाद कब्जा क्या। अपवाद लॉगिंग की तरह, और स्टैक ट्रेस सहित? – Llyle

4

मान लीजिए कि मुझे उन परेशानियों की रिपोर्ट है जो पुन: उत्पन्न करने में कठोर हैं, मुझे हमेशा कोड पढ़ने, अधिमानतः जोड़ी-कोड-रीडिंग पढ़कर मिलती है, ताकि आप थ्रेडिंग सेमेन्टिक्स/लॉकिंग जरूरतों पर चर्चा कर सकें। जब हम पर आधारित समस्या पर आधारित करते हैं, तो मुझे लगता है कि हम हमेशा एक या अधिक समस्याओं को तुरंत जल्दी से नाखून करते हैं। मुझे लगता है कि यह मुश्किल समस्याओं को हल करने के लिए एक काफी सस्ता तकनीक भी है।

क्षमा करें, आपको ctrl + shift + f13 दबाए जाने के लिए बताने में सक्षम न होने के लिए खेद है, लेकिन मुझे नहीं लगता कि ऐसा कुछ भी उपलब्ध है। लेकिन बस के बारे में सोच रहे हैं रिपोर्ट की गई समस्या वास्तव में आमतौर पर कोड में दिशा की काफी मजबूत भावना देती है, इसलिए आपको मुख्य() पर प्रारंभ करने की आवश्यकता नहीं है।

+0

हां, किस कोड के बारे में बात करनी चाहिए और वास्तव में यह क्या कर रहा है, बहुत मदद करता है! – MicSim

1

विजुअल स्टूडियो आपको प्रत्येक थ्रेड के कॉल स्टैक का निरीक्षण करने की अनुमति देता है, और आप उनके बीच स्विच कर सकते हैं। यह सभी प्रकार के थ्रेडिंग मुद्दों को ट्रैक करने के लिए पर्याप्त नहीं है, लेकिन यह एक शुरुआत है। आने वाले वीएस -2010 के लिए बहु-थ्रेडेड डीबगिंग के लिए बहुत सारे सुधार की योजना बनाई गई है।

मैंने .NET कोड में थ्रेडिंग समस्याओं के लिए WinDbg + SoS का उपयोग किया है। आप ताले का निरीक्षण कर सकते हैं (सिंक ब्लॉक्स), थ्रेड कॉल स्टैक इत्यादि।

+0

सोस एक डीएलएल है जो WinDbg के तहत प्रबंधित डिबगिंग सक्षम करता है। –

4

आपके द्वारा पहले से प्राप्त किए गए अन्य अच्छे उत्तरों के अलावा: ग्राहक के उपयोग के रूप में कम से कम प्रोसेसर/प्रोसेसर कोर के साथ मशीन पर हमेशा परीक्षण करें, या आपके प्रोग्राम में सक्रिय थ्रेड हैं। अन्यथा कुछ मल्टीथ्रेडिंग बग पुन: उत्पन्न करने के लिए असंभव हो सकता है।

0

कोड the way that Princess recommended for your other question (अपरिवर्तनीय वस्तुएं, और एरलांग-शैली संदेश उत्तीर्ण) विकसित करें। बहु-थ्रेडिंग समस्याओं का पता लगाना आसान होगा, क्योंकि धागे के बीच बातचीत अच्छी तरह से परिभाषित की जाएगी।

5

क्रैश डंप के अलावा, एक तकनीक व्यापक रन-टाइम लॉगिंग होती है: जहां प्रत्येक थ्रेड लॉग करता है कि यह क्या कर रहा है।

पहला प्रश्न जब कोई त्रुटि रिपोर्ट की जाती है, तो हो सकता है, "लॉग फ़ाइल कहां है?"

कभी-कभी आप लॉग फ़ाइल में समस्या देख सकते हैं: "यह धागा यहां एक अवैध/अप्रत्याशित स्थिति का पता लगा रहा है ... और देखो, यह दूसरा धागा ऐसा कर रहा था, बस पहले और/या इसके बाद।"

यदि लॉग फ़ाइल यह नहीं कहती कि क्या हो रहा है, तो ग्राहक से क्षमा मांगें, कोड में पर्याप्त अतिरिक्त लॉगिंग स्टेटमेंट जोड़ें, ग्राहक को नया कोड दें, और कहें कि आप इसे ठीक कर देंगे इसे एक बार होता है।

+0

लॉग फ़ाइल के साथ बहुप्रचारित समस्याओं का विश्लेषण अक्सर प्रोग्राम के गतिशील व्यवहार को बहुत अधिक बदल देता है। मेमोरी ट्रेस में बेहतर उपयोग करें और समस्या होने के बाद स्मृति फ़ाइल को केवल एक फ़ाइल में कॉपी करें। मेरे उत्तर में अधिक जानकारी देखें। –

1

Tess Ferrandez's blog .NET में डिबग गतिरोध को WinDbg का उपयोग कर के अच्छे उदाहरण हैं।

-6

सबसे अच्छी बात मैं के बारे में सोच सकते हैं मल्टी-थ्रेडेड कोड जब भी संभव से दूर रहने के लिए है। यह वहाँ लगता है बहुत कम प्रोग्रामर हैं जो बग फ्री मल्टी थ्रेडेड एप्लिकेशन लिख सकते हैं और मैं तर्क दूंगा कि बग फ्री बड़े मल्टी लिखने में सक्षम कोई कोडर मधुमक्खी नहीं है थ्रेडेड अनुप्रयोगों।

+0

अच्छा, आप कैसे जानते हैं कि कोई भी बड़ा एप्लिकेशन (सिंगल या मल्टी थ्रेडेड) बग फ्री है? आप नहीं कर सकते लेकिन इसके अलावा मुझे लगता है कि यदि आप नियमों को जानते हैं और मानते हैं तो अपेक्षाकृत सुरक्षित बहु-थ्रेडेड कोड लिखना संभव है। बेहतर प्रदर्शन पाने की कोशिश करने में अधिकांश समय बग पेश करेंगे, हालांकि। – mghie

+6

अब सही रवैया है! चलो छोड़ दें क्योंकि यह मुश्किल है; जो परिमाण की मात्रा के बारे में परवाह करता है संभावित प्रदर्शन लाभ मेरे आवेदन को थोड़ा सा विचार से प्राप्त हो सकता है! क्योंकि हम सभी जानते हैं कि सिंगल थ्रेडेड ऐप्स में कोई बग नहीं है: पी – MatthewJ

+0

@MatthewJ बिल्कुल। सोमवार के समय लाभ लाभ के लायक नहीं हैं। बहुत से लोग परमाणु ऊर्जा के बारे में सोचते हैं। मैं बहुप्रचारित कोड के बारे में करता हूं। – max

1

जोर दें() रेस-स्थितियों का पता लगाने के लिए आपका मित्र है। जब भी आप एक महत्वपूर्ण खंड में प्रवेश करते हैं, तो जोर दें कि इसके साथ जुड़े आविष्कार सत्य हैं (यही सीएस के लिए है)। हालांकि, दुर्भाग्यवश, चेक महंगा हो सकता है और इस प्रकार उत्पादन वातावरण में उपयोग के लिए उपयुक्त नहीं है।

5

जावा के लिए एक सत्यापन उपकरण है जिसे javapathfinder कहा जाता है जिसे मुझे कोड से संभावित दौड़ की स्थिति और मौत-लॉक कीड़े के खिलाफ बहु-थ्रेडिंग एप्लिकेशन को डीबग और सत्यापित करने में उपयोगी लगता है।
यह ग्रहण और नेटबीन आईडीई दोनों के साथ बारीकी से काम करता है।

0

मुझे एक थ्रेड समस्या का सामना करना पड़ा जो समान गलत परिणाम दे रहा था और जब भी अन्य स्थितियों (स्मृति, शेड्यूलर, प्रोसेसिंग लोड) कम या समान थे, तब से अप्रत्याशित रूप से व्यवहार नहीं कर रहा था।

मेरे अनुभव से, मैं कह सकता हूं कि हरडेस्ट भाग यह पहचानना है कि यह एक थ्रेड मुद्दा है, और सर्वोत्तम समाधान बहु-थ्रेडेड कोड की सावधानीपूर्वक समीक्षा करना है। थ्रेड कोड पर ध्यान से देखकर आपको यह पता लगाने की कोशिश करनी चाहिए कि क्या गलत हो सकता है। अन्य तरीकों (थ्रेड डंप, प्रोफाइलर इत्यादि) इसके लिए दूसरे स्थान पर आ जाएंगे।

1

मैंने रनटाइम के दौरान जावा कार्यक्रमों में दौड़ की स्थिति का पता लगाने के लिए टूल vmlens लागू किया। यह eraser नामक एल्गोरिदम लागू करता है।

+0

उन्नत इरेज़र? –

+0

असल में, मैंने एल्गोरिदम बदल दिया। vmlens अब विश्लेषण सभी समवर्ती रूप से उपयोग किए गए क्षेत्रों के रिश्ते से पहले होता है। –

3

कभी-कभी, बहुप्रचारित समाधानों से बचा नहीं जा सकता है। यदि कोई बग है, तो वास्तविक समय में इसकी जांच की जानी चाहिए, जो विजुअल स्टूडियो जैसे अधिकांश उपकरणों के साथ लगभग असंभव है।

  1. नहीं किसी देरी
  2. जोड़ने किसी भी ताला लगा
  3. multithreading जा सुरक्षित
  4. का पता लगाने क्या सही क्रम में हुआ उपयोग नहीं: हालांकि ट्रेसिंग ही चाहिए केवल व्यावहारिक समाधान, निशान लिखने के लिए है।

यह एक असंभव कार्य की तरह लगता है, लेकिन इसे आसानी से स्मृति में ट्रेस लिखकर हासिल किया जा सकता है। सी # में, यह कुछ इस तरह दिखेगा:

public const int MaxMessages = 0x100; 
string[] messages = new string[MaxMessages]; 
int messagesIndex = -1; 

public void Trace(string message) { 
    int thisIndex = Interlocked.Increment(ref messagesIndex); 
    messages[thisIndex] = message; 
} 

विधि ट्रेस() सुरक्षित, गैर अवरुद्ध multithreading है और किसी भी धागे से कहा जा सकता है। मेरे पीसी पर, निष्पादित करने में लगभग 2 माइक्रोसेकंड लगते हैं, जो पर्याप्त तेज़ होना चाहिए।

जहां भी आपको लगता है कि कुछ गलत हो सकता है, प्रोग्राम चलाएं, त्रुटि होने तक प्रतीक्षा करें, ट्रेस को रोकें और फिर किसी भी त्रुटि के लिए ट्रेस की जांच करें।इस दृष्टिकोण जो भी धागा और समय जानकारी एकत्र करता है, के लिए

एक अधिक विस्तृत विवरण बफर recycles और पर आउटपुट ट्रेस अच्छी तरह से आप पा सकते हैं: CodeProject: वास्तविक समय में बहु कोड डीबग करना 1

1

साथ एक छोटी सी चार्ट multithreaded कोड डीबगिंग में ध्यान में रखने के लिए कुछ डीबगिंग तकनीकें। चार्ट बढ़ रहा है, कृपया टिप्पणी करने के लिए टिप्पणियां और सुझाव छोड़ दें। (this link पर अपडेट फाइल)

Multithreaded debugging chart

-2

मैं जीएनयू उपयोग कर रहा हूँ और प्रयोग सरल स्क्रिप्ट

$ अधिक gdb_tracer

b func.cpp:2871 
r 
#c 
while (1) 
next 
#step 
end 
संबंधित मुद्दे