2010-04-21 6 views
6

मेरे पास एक थ्रेड ए है जो स्मृति आवंटित करता है और इसे साझा पॉइंटर को असाइन करता है। फिर यह धागा एक्स, वाई और जेड 3 अन्य धागे पैदा करता है और साझा पॉइंटर की एक प्रति प्रत्येक को पास करता है। जब एक्स, वाई और जेड गुंजाइश से बाहर निकलते हैं, तो स्मृति मुक्त हो जाती है। लेकिन क्या संभावना है कि 2 धागे एक्स, वाई समय के ठीक उसी बिंदु पर दायरे से बाहर निकलते हैं और संदर्भ संख्या पर दौड़ की स्थिति होती है, इसलिए इसे 2 से कम करने की बजाय, यह केवल एक बार घट जाती है। तो, अब संदर्भ 0 पर नई बूंदों की गिनती है, इसलिए एक स्मृति रिसाव है। ध्यान दें कि, एक्स, वाई और जेड केवल स्मृति पढ़ रहे हैं। साझा सूचक को लिखना या रीसेट करना नहीं। एक लंबी कहानी को कम करने के लिए, क्या संदर्भ गणना पर दौड़ की स्थिति हो सकती है और क्या इससे स्मृति रिसाव हो सकता है?साझा पॉइंटर को बढ़ावा दें: एकाधिक थ्रेड में एक साथ पढ़ने की पहुंच

+0

दिलचस्प है कि दो लोगों ने विरोध निष्कर्ष तक पहुंचने के लिए एक ही दस्तावेज का उपयोग किया था। –

+0

@ मार्क: मैं कहूंगा कि दस्तावेज़ पूरी तरह से क्रिस्टल-स्पष्ट नहीं हैं (यह नहीं कहने के लिए कि वे गलत हैं, बस इतना कि वे आसानी से गलत व्याख्या कर रहे हैं)। –

+0

मुझे समझ में नहीं आता कि आपने अपना प्रश्न क्यों दिया है।जवाब पहले से ही है :) –

उत्तर

2

कई अन्य लोगों ने पहले से ही दस्तावेज के लिंक प्रदान किए हैं जो यह बताते हैं कि यह सुरक्षित है।

बिल्कुल अचूक सबूत के लिए, देखें कि बूस्ट स्मार्टप्टर वास्तव में boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp (या आपके प्लेटफ़ॉर्म की संबंधित फ़ाइल) में स्क्रैच से अपने स्वयं के म्यूटेक्स को कैसे लागू करता है।

6

नहीं है, the documentation के अनुसार, इन समस्याओं घटित नहीं कर सकते हैं:

अलग shared_ptr उदाहरणों "के लिए लिखा" किया जा सकता है (जैसे कि ऑपरेटर के रूप में अस्थायी संचालन का उपयोग करके पहुँचा = या रीसेट) simultaneosly से अधिक थ्रेड द्वारा (भी जब इन उदाहरणों प्रतियां हैं, और नीचे एक ही संदर्भ गिनती का हिस्सा।)

+0

मेरे पास एक प्रश्न है हालांकि: दस्तावेज के अनुसार, मिश्रित स्थिति अपरिभाषित हो सकती है beahvior: (...) // --- उदाहरण 4 --- // धागा ए पी 3 = पी 2; //, p2 पढ़ता दायरे से बाहर चला जाता है p3 // धागा // p2 लिखते हैं: अपरिभाषित, नाशक माना जाता है एक "लिखने" (...) हम इस स्थिति यहाँ में नहीं हैं? – Grimmy

+0

नीचे दिया गया उदाहरण जो व्यवहार को 'अपरिभाषित' के रूप में दिखाता है जब यह दायरे से बाहर हो जाता है। –

+1

@Grimmy, @Brian: उदाहरण में 4 मेरी प्रस्तुति में प्रलेखन में एक धागा अन्य थ्रेड में रहने वाले 'shared_ptr' चर को पढ़ने की कोशिश करता है, जबकि यह चर गुंजाइश से बाहर हो जाता है। यह अनिर्धारित होगा (और यह अन्य प्रकार के चर के लिए भी अनिर्धारित नहीं होगा, न केवल 'shared_ptr')। यदि प्रत्येक थ्रेड को 'shared_ptr' चर की अपनी प्रति प्राप्त हो जाती है, तो उन चरों का उपयोग स्वतंत्र रूप से (और दायरे से बाहर जाना) किया जा सकता है, भले ही वे एक ही ऑब्जेक्ट को इंगित करें (उदाहरण के लिए प्रलेखन में 2)। – sth

12

boost::shared_ptr ताले का उपयोग करता है (या ताला मुक्त परमाणु पहुँच) यह सुनिश्चित करने के संदर्भ में गिना जाता है atomically अपडेट किया जाता है (भले ही यह दस्तावेज़ पृष्ठ से स्पष्ट नहीं है)। यदि आप मैक्रो BOOST_SP_DISABLE_THREADS को परिभाषित करके एकल थ्रेडेड कोड लिख रहे हैं तो आप ताले के उपयोग को दूर कर सकते हैं।

ध्यान दें कि http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety में प्रलेखन उदाहरण है कि अलग अलग धागे से कई राईट के साथ समस्याओं पर चर्चा उन धागे एक ही shared_ptr उदाहरणों पर अभिनय पर चर्चा कर रहा है, नहीं अलग shared_ptr प्रतियां कि को इंगित (shared_ptr वस्तुओं उदाहरण में वैश्विक हो सकता है) एक ही ऑब्जेक्ट, जो shared_ptr के लिए सामान्य उपयोग केस है। उदाहरण में आप जो उदाहरण देते हैं (साझा ऑब्जेक्ट को इंगित करने वाली प्रतियों पर कार्य करना) थ्रेड-सुरक्षित है।

+0

टिप्पणी बिल्कुल सही है, लेकिन मैं यह भी जोड़ूंगा कि कुछ वस्तुओं के विनाशक को "गलत" थ्रेड से या "गलत" समय पर कॉल करना, रेस और डेडलॉक्स जैसे बहु-थ्रेडेड बग के सामान्य प्रकार बना सकता है। यदि नष्ट वस्तु केवल स्मृति को मुक्त करती है, तो यह कोई समस्या नहीं होनी चाहिए। हालांकि, विनाशक जो सिस्टम के अन्य हिस्सों के साथ विनाशकारी वस्तु को अपंजीकृत करने जैसी चीजें करते हैं, निश्चित रूप से समस्याएं पैदा कर सकते हैं। – Doug

+0

@Doug जिसका 'shared_ptr' के साथ कुछ लेना देना नहीं है, हालांकि। "यह क्रैश हो गया क्योंकि यह गलत समय पर गलत जगह पर था" की तुलना में लॉक किए गए विशेष पहुंच के संदर्भ में सोचना बेहतर है। जो भी संसाधन विनाशकों का उपयोग खुद को बंद कर देना चाहिए। – Potatoswatter

+0

@Potatoswatter: हाँ, मैं समझता हूं कि मैंने जो समस्या उठाई है उसे साझा_ptr की थ्रेड सुरक्षा के साथ सीधे नहीं करना है। मैं दौड़ की स्थिति के बारे में नहीं सोचता क्योंकि "यह गलत समय पर गलत जगह पर था"। मुझे share_ptrs के कारण कीड़े मिली हैं जो एक गैर-मुख्य धागे (कहें) पर अपना अंतिम संदर्भ खो देते हैं और जहां विनाशक गैर-तुच्छ सफाई करता है। दस्तावेज कहता है कि पॉइंटर को मैन्युअल रूप से हटाने के समान ही है - "कच्चे पॉइंटर्स के समान थ्रेड सुरक्षा"। – Doug

1

documentation का कहना है:

अलग shared_ptr उदाहरणों "लिखा करने के लिए" किया जा सकता है (जैसे कि ऑपरेटर के रूप में अस्थायी संचालन का उपयोग करके पहुँचा = या रीसेट) simultaneosly से अधिक थ्रेड (तब भी जब इन उदाहरणों प्रतियां हैं, और साझा करने के द्वारा नीचे एक ही संदर्भ गिनती।)

तो यदि धागे में से कोई भी अन्य धागे की पॉइंटर ऑब्जेक्ट्स तक पहुंच नहीं पाता है, तो यह ठीक होना चाहिए। कृपया दस्तावेज़ीकरण में उदाहरण देखें और देखें कि आपके मामले में कौन सा प्रासंगिक है।

-2

बूस्ट किस्म के विपरीत, सबसे अच्छा काम TR1 या C++ 0x shared_ptr में अपग्रेड करना होगा। मेरा मानना ​​है कि यह मानकीकृत है कि वे थ्रेड-सुरक्षित होना चाहिए।

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