2012-07-25 21 views
6

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

class TestClass 
{ 
public: 

    TestClass(const float input) : 
     mMutex(), 
     mValueOne(1), 
     mValueTwo("Text") 
    { 
     //**Does the mutex need to be locked here? 
     mValueTwo.Set(input); 
     mValueOne = mValueTwo.Get(); 
    } 

    ~TestClass() 
    { 
    //Lock Here? 
    } 

    int GetValueOne() const 
    { 
     Lock(mMutex); 
     return mValueOne; 
    } 

    void SetValueOne(const int value) 
    { 
     Lock(mMutex); 
     mValueOne = value; 
    } 

    CustomType GetValueTwo() const 
    { 
     Lock(mMutex); 
     return mValueOne; 
    } 

    void SetValueTwo(const CustomType type) 
    { 
     Lock(mMutex); 
     mValueTwo = type; 
    } 

private: 

    Mutex mMutex; 
    int mValueOne; 
    CustomType mValueTwo; 
}; 
पाठ्यक्रम सब कुछ के

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

+3

जब आप कहते हैं कि 'क्लास' है एकाधिक धागे के बीच प्रयोग किया जाता है, मुझे लगता है कि आप का मतलब है कि टेस्ट क्लास प्रकार का ऑब्जेक्ट कई धागे में उपयोग किया जा सकता है। उस स्थिति में, आप अभी भी केवल एक वस्तु बना रहे हैं, इसलिए आपको कन्स्ट्रक्टर में लॉकिंग की आवश्यकता नहीं है। यदि दोनों धागे एक ही समय में कन्स्ट्रक्टर में हैं, तो वे 2 अलग-अलग वस्तुएं बना रहे हैं। ऑब्जेक्ट निर्माण के चारों ओर लॉक करने के लिए यह अधिक समझ में आता है, सुनिश्चित करने के लिए (उदाहरण के लिए) वस्तु का निर्माण समाप्त होने से पहले mValueTwo का उपयोग नहीं किया जाता है। विनाशक को लगता है कि इसे लॉक करना चाहिए, यह सुनिश्चित करने के लिए कि नष्ट होने के दौरान डेटा तक पहुंचा नहीं जा सके। – Rollie

+0

@ रोली हां, मेरा मतलब था कि ऑब्जेक्ट साझा किया जाएगा। इसलिए, यदि मैं बना देता हूं: – Brett

+1

@Rollie: इसे नष्ट करने के दौरान कक्षा तक पहुंच उदाहरणों के साथ एक बग है जीवन-प्रबंधन प्रबंधन - जब ऐसा होता है तो कार्यक्रम पहले से ही टूट जाता है (यदि इसे नष्ट करने के दौरान उपयोग किया जा सकता है, तो यह बाद में भी हो सकता है)। –

उत्तर

12

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

विनाश थोड़ा कठिन मामला है। लेकिन फिर, आपके ऑब्जेक्ट का उचित आजीवन प्रबंधन यह सुनिश्चित कर सकता है कि कोई ऑब्जेक्ट कभी नष्ट नहीं होता है जब कुछ थ्रेड (ओं) इसका उपयोग कर सकते हैं।

एक साझा सूचक इस तरह प्राप्त करने में मदद कर सकता है। :

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

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

+1

एक साझा_प्टर का उपयोग करना सामान्य रूप से अपर्याप्त है। ऐसा इसलिए है क्योंकि shared_ptr को छोड़ने वाला अंतिम धागा विनाशक को चलाएगा, लेकिन वह धागा वस्तु को संशोधित करने के लिए अंतिम धागा नहीं हो सकता है। यदि ऑब्जेक्ट में वेक्टर या मैप जैसे जटिल डेटा सदस्य होते हैं, और विनाशक लॉक प्राप्त नहीं करता है और लॉक नहीं करता है, तो विनाशक बेवकूफ स्मृति देख सकता है और क्रैश का कारण बन सकता है। –

+0

@ मिचीहेनिंग: एक धागा केवल इसके साझा सूचक * को जारी करेगा * के बाद * यह ऑब्जेक्ट पर सभी परिचालनों को पूरा करता है - जो एक बहुत ही उचित (यदि स्पष्ट नहीं है) आवश्यकता है। तो, लॉकिंग अनावश्यक है। पुरानी याददाश्त वास्तव में सैद्धांतिक रूप से संभव है, लेकिन इससे निपटने के लिए, आपको लॉकिंग नहीं, स्मृति बाधा की आवश्यकता है। (दी गई, कई लोकप्रिय थ्रेडिंग पुस्तकालयों में कुछ लॉक ऑपरेशंस के साथ बाधा शामिल है, इसलिए हो सकता है कि आप इसका मतलब लें) –

+0

यहां परिदृश्य है। थ्रेड ए में shared_ptr बनाएं और साझा_ptr (सही ढंग से इंटरलॉकिंग) को थ्रेड बी पर पास करें। थ्रेड एक foo की स्थिति अपडेट करता है और इसके पॉइंटर को छोड़ देता है। बाद में, थ्रेड बी ने अपने shared_ptr को छोड़ दिया, जिससे थ्रेड बी को foo के विनाशक को कॉल करने का कारण बनता है। यदि थ्रेड बी ने अंतिम अद्यतन foo के बाद मेमोरी बाधा पार नहीं किया है, तो foo का विनाशक स्टेल डेटा पर काम करेगा। यदि foo में एक जटिल डेटा सदस्य है, जैसे नक्शा, जो क्रैश का कारण बन सकता है। आप सही हैं कि एक स्मृति बाधा की आवश्यकता है। ऐसा ही होता है कि एक म्यूटेक्स भी बाधा उत्पन्न करता है। –

1

वे निर्माता में बंद किया जाना है, के रूप में एक ही तरीका है किसी को भी बाहरी है यदि आप निर्माता से ही चारों ओर उन्हें पारित उस बिंदु पर है कि डेटा तक पहुँच प्राप्त कर सकते हैं की जरूरत नहीं है (या बुला की तरह, कुछ अपरिभाषित व्यवहार करना एक वर्चुअल विधि)।

[संपादित करें: नाशक के बारे में निकाला गया हिस्सा है, के बाद से के रूप में एक टिप्पणी हक का दावा है, तो आप बड़ी समस्या है तो आप एक वस्तु जो मृत हो सकता है से पहुँच संसाधनों के लिए कोशिश कर रहे हैं]

+1

यदि कोई अन्य धागा नष्ट हो रहा है, तो ऑब्जेक्ट तक पहुंच सकता है, तो आपके पास एक बग है और लॉकिंग मदद नहीं करेगा (विचार करें कि क्या होता है यदि नष्ट करने वाला धागा पहले म्यूटेक्स प्राप्त करता है)। साथ ही, मुझे नहीं लगता कि 'shared_ptr' में mutex को लपेटने वाला क्या होगा। – interjay

+0

आप सही हैं, मैं मानता हूं कि अगर आपको कोई मौका है कि आप मरने वाले किसी ऑब्जेक्ट से डेटा तक पहुंच रहे हैं तो आपको कोई समस्या है। Shared_ptr प्रस्ताव उस स्थिति से बचने के लिए था जहां म्यूटेक्स ऑब्जेक्ट के साथ नष्ट हो गया था, लेकिन मुझे लगता है कि उस ऑब्जेक्ट में किसी भी चीज़ तक पहुंचने से पहले आपको उस म्यूटेक्स को लॉक करना होगा, इसलिए यह ऑब्जेक्ट के अंदर काम नहीं करता है। मैं अपना जवाब संपादित करूंगा। –

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