2010-08-18 14 views
6

यह स्मृति प्रबंधन के मुद्दों पर पिछले पोस्ट करने के लिए अपने अनुवर्ती अप है। निम्नलिखित मुद्दे हैं जिन्हें मैं जानता हूं।थ्रेड से संबंधित मुद्दों और उन्हें डिबगिंग

1) डेटा दौड़ (atomicity उल्लंघन और डेटा भ्रष्टाचार)

2) आदेश देने समस्याओं

3) मृत ताले

4) heisenbugs

किसी भी अन्य मुद्दों के लिए अग्रणी ताले के दुरुपयोग बहु थ्रेडिंग के साथ? उन्हें कैसे हल करें? theading साथ

उत्तर

2

एरिक की चार मुद्दों की सूची काफी अधिक है। लेकिन इन मुद्दों को डीबग करना मुश्किल है।

डेडलॉक के लिए, मैंने हमेशा "लेवल लॉक" का पक्ष लिया है। अनिवार्य रूप से आप प्रत्येक प्रकार के लॉक को एक स्तर संख्या देते हैं। और उसके बाद एक थ्रेड एक्वायर ताले की आवश्यकता होती है जो monotonic हैं।

लगाया ताले करने के लिए, अगर आप इस तरह एक संरचना की घोषणा कर सकते हैं:

typedef struct { 
    os_mutex actual_lock; 
    int level; 
    my_lock *prev_lock_in_thread; 
} my_lock_struct; 

static __tls my_lock_struct *last_lock_in_thread; 

void my_lock_aquire(int level, *my_lock_struct lock) { 
    if (last_lock_in_thread != NULL) assert(last_lock_in_thread->level < level) 
    os_lock_acquire(lock->actual_lock) 
    lock->level = level 
    lock->prev_lock_in_thread = last_lock_in_thread 
    last_lock_in_thread = lock 
} 

क्या लगाया ताले के बारे में अच्छा है है गतिरोध की संभावना एक अभिकथन कारण बनता है। और FUNC और LINE के साथ कुछ अतिरिक्त जादू के साथ आप जानते हैं कि आपके धागे ने वास्तव में क्या बुराई की है।

डेटा दौड़ और सिंक्रनाइज़ेशन की कमी के लिए, वर्तमान स्थिति बहुत खराब है। ऐसे स्थिर उपकरण हैं जो मुद्दों की पहचान करने का प्रयास करते हैं। लेकिन झूठी सकारात्मक उच्च हैं।

जिस कंपनी के लिए मैं काम करता हूं (http://www.corensic.com) में जिन्क्स नामक एक नया उत्पाद है जो सक्रिय रूप से ऐसे मामलों की तलाश करता है जहां दौड़ की स्थिति का खुलासा किया जा सकता है। यह विभिन्न CPUs पर धागे के अंतराल को नियंत्रित करने और CPUs के बीच संचार पर ज़ूम करने के लिए वर्चुअलाइजेशन तकनीक का उपयोग करके किया जाता है।

इसे देखें। बीटा को मुफ्त में डाउनलोड करने के लिए आपके पास शायद कुछ और दिन हैं।

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

1

चार सबसे आम समस्याएं हैं

1-डेडलॉक
2-Livelock
3-रेस स्थितियां
4-भुखमरी

+1

बहुत बहुत धन्यवाद लेकिन इन मुद्दों को हल करने के लिए कैसे? – brett

+0

इन सभी समस्याओं को सेमफोर (ताले) के साथ हल किया जा सकता है। आपको सावधानीपूर्वक समझना होगा कि आप पहले क्या कर रहे हैं। थ्रेड के साथ ऐसा करने की कोशिश न करें, वे आपके प्रोग्राम को सामान करने में मदद करने के लिए एक उपकरण हैं, न कि कुछ जादुई चाल जिन्हें आपको जगह पर रखना होगा – Eric

1

कैसे हल करने के लिए [बहु सूत्रण के साथ मुद्दों] ?

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

तैयार करें और उस के लिए योजना। शुरुआत से अपने आवेदन में एक अच्छी लॉगिंग सुविधा शामिल करें।

2

दुर्भाग्य से वहाँ कोई अच्छा गोली कि स्वचालित रूप से सबसे सभी सूत्रण मुद्दों को हल में मदद करता है/है। यहां तक ​​कि इकाई परीक्षण जो कोड के सिंगल-थ्रेडेड टुकड़ों पर इतना अच्छा काम करते हैं, कभी भी बेहद सूक्ष्म दौड़ की स्थिति का पता नहीं लगा सकते हैं।

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

1

यथासंभव सरल अपने धागे करें।

वैश्विक चर का उपयोग नहीं करने की कोशिश करो। वैश्विक स्थिरांक (वास्तविक स्थिरांक जो कभी नहीं बदलते) ठीक है। जब आपको वैश्विक या साझा चर का उपयोग करने की आवश्यकता होती है तो आपको उन्हें किसी प्रकार के म्यूटेक्स/लॉक (सेमफोर, मॉनिटर, ...) से बचाने की आवश्यकता होती है।

यह सुनिश्चित करें कि आप वास्तव में समझने की क्या कैसे अपने mutexes काम करें। कुछ अलग-अलग कार्यान्वयन हैं जो अलग-अलग काम कर सकते हैं।

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

समझने के लिए अधिक धागे वास्तव में आप के लिए करता है की कोशिश करो।किसी समस्या पर अंधेरे से अधिक धागे फेंकना अक्सर चीजों को और खराब करने जा रहा है। विभिन्न धागे सीपीयू और ताले के लिए प्रतिस्पर्धा करते हैं।

डेडलॉक परिहार नियोजन की आवश्यकता है। एक समय में एक से अधिक ताला हासिल करने से बचने के लिए प्रयास करें। यदि यह आदेश देने पर अपरिहार्य है तो आप सभी धागे के लिए ताले हासिल करने और रिलीज़ करने के लिए उपयोग करेंगे। सुनिश्चित करें कि आप जानते हैं कि वास्तव में क्या डेडलॉक का मतलब है।

मल्टी-थ्रेडेड या वितरित अनुप्रयोगों डिबगिंग मुश्किल है। आप एक ही लड़ी वातावरण में डिबगिंग के सबसे कर सकते हैं (हो सकता है यहां तक ​​कि बस अन्य थ्रेड सोने के लिए मजबूर कर रहा) तो आप मल्टी-थ्रेडेड डिबगिंग में कूदने से पहले केंद्रित कीड़े गैर सूत्रण को खत्म करने की कोशिश कर सकते हैं।

उसका हमेशा अन्य थ्रेड अप करने के लिए हो सकता है के बारे में सोचते हैं। इसे अपने कोड में टिप्पणी करें। यदि आप कुछ निश्चित तरीके से कर रहे हैं क्योंकि आप जानते हैं कि उस समय कोई अन्य थ्रेड किसी निश्चित संसाधन तक नहीं पहुंचना चाहिए, तो ऐसा कहने पर एक बड़ी टिप्पणी लिखें।

पूर्णांक my_lock_get (lock_type ताला, स्थिरांक चार * फ़ाइल, अहस्ताक्षरित लाइन, स्थिरांक चार * संदेश) {

thread_id_type me = this_thread(); 

logf("%u\t%s (%u)\t%s:%u\t%s\t%s\n", time_now(), thread_name(me), me, "get", msg); 

lock_get(lock); 

logf("%u\t%s (%u)\t%s:%u\t%s\t%s\n", time_now(), thread_name(me), me, "in", msg); 
:

आप म्युटेक्स ताले के लिए कॉल रैप करने के लिए चाहते हो सकता है/जैसे अन्य कार्यों में बातें बताता है

}

और अनलॉक करने के लिए एक समान संस्करण। ध्यान दें, इसमें उपयोग किए गए फ़ंक्शंस और प्रकार सभी किसी भी एक एपीआई के आधार पर बनाए गए हैं और अधिकतर नहीं हैं।

इस तरह का उपयोग करने से आप वापस आ सकते हैं यदि कोई त्रुटि है और एक पर्ल स्क्रिप्ट का उपयोग करें या कुछ ऐसा कहने के लिए जैसे कि चीजें गलत हो गई हैं (लॉक से मेल खाता है और उदाहरण के लिए अनलॉक करता है)।

ध्यान दें कि आपके प्रिंट या लॉगिंग कार्यक्षमता के साथ-साथ इसके चारों ओर ताले होने की आवश्यकता हो सकती है। कई पुस्तकालयों में पहले से ही यह बनाया गया है, लेकिन सभी नहीं करते हैं। इन ताले को लॉक_ [get | release] फ़ंक्शंस के प्रिंटिंग संस्करण का उपयोग करने की आवश्यकता नहीं है या आपके पास अनंत रिकर्सन होगा।

1
  1. ++ वैश्विक चर से सावधान रहें भी अगर वे सी में विशेष रूप से const कर रहे हैं। केवल पीओडी जो स्थिर रूप से प्रारंभिक "à la" सी यहां अच्छे हैं। जैसे ही रन-टाइम कन्स्ट्रक्टर खेल में आता है, बेहद सावधान रहें। में स्थिर लिंकेज वाले वैरिएबल के एएफएआईआर प्रारंभिक क्रम विभिन्न संकलन इकाइयां एक अपरिभाषित क्रम में बुलाई गई हैं। हो सकता है कि सी ++ कक्षाएं जो सभी को उनके सदस्यों को ठीक से प्रारंभ करें और खाली फ़ंक्शन बॉडी हो, तो आजकल ठीक हो सकता है, लेकिन मुझे एक बार अनुभव भी खराब था।

    क्यों POSIX तरफ pthread_mutex_t ज्यादा आसान sem_t से कार्यक्रम है यही कारण है में से एक है: यह एक स्थिर प्रारंभकर्ता PTHREAD_MUTEX_INITIALIZER है।

  2. यथासंभव कम महत्वपूर्ण वर्गों रखें, दो कारणों के लिए: यह अंत में और अधिक कुशल हो सकता है, लेकिन अधिक महत्वपूर्ण बात यह के लिए आसान बनाए रखने और डिबग करने के लिए है।

    एक महत्वपूर्ण खंड कभी नहीं अब होना चाहिए कि लॉक और अनलॉक करना कि की जरूरत है उसे बचाने के लिए, और टिप्पणियों और दावे जो मदद पाठक को समझने के लिए क्या हो रहा है सहित एक स्क्रीन,।

    प्रारंभ बहुत सख्ती से उन सब के लिए एक वैश्विक लॉक के साथ हो सकता है महत्वपूर्ण वर्गों को लागू करने, और बाधाओं बाद में आराम करो।

  3. लॉगिंग शायद मुश्किल हो सकती है अगर धागे उसी समय पर लिखने लगते हैं। यदि प्रत्येक थ्रेड काम की उचित मात्रा पर प्रयास करता है तो उनमें से प्रत्येक अपने की फ़ाइल लिखता है, जैसे कि वे एक दूसरे को इंटरलॉक नहीं करते हैं।

    लेकिन सावधान रहें, कोड के व्यवहार व्यवहार लॉग इन करें। यह खराब हो सकता है जब गायब हो जाते हैं, या फायदेमंद होते हैं जब बग्स दिखाई देते हैं कि आप अन्यथा ध्यान नहीं देंगे।

    इस तरह के एक गड़बड़ की पोस्टमार्टम विश्लेषण करने के लिए आप प्रत्येक पंक्ति इस तरह के सभी फाइलों विलय कर दिया हो सकता है और आप निष्पादन की एक सुसंगत दृश्य दे सकते हैं कि पर सही टाइम स्टांप करना होगा।

1

-> उस सूची में प्राथमिकता जोड़ें।

जैसा कि एक अन्य पोस्टर से जुड़ा हुआ है, लॉग फाइलें अद्भुत चीजें हैं। डेडलॉक्स के लिए, के बजाय LogLock का उपयोग करके जब आप इकाइयां काम करना बंद कर देते हैं तो पिनपॉइंट की सहायता कर सकते हैं। यही है, एक बार जब आपको पता चले कि आपको डेडलॉक मिल गया है, तो लॉग आपको बताएगा कि कब और कहाँ ताले तत्काल और रिहा किए गए थे। इन चीजों को ट्रैक करने में यह बहुत उपयोगी हो सकता है।

मुझे एक ही संदेश के बाद एक अभिनेता मॉडल का उपयोग करते समय दौड़ की स्थिति मिली है-> पुष्टि-> प्राप्त शैली की पुष्टि गायब होने लगती है। उस ने कहा, वाईएमएमवी।

संबंधित मुद्दे