2011-09-06 11 views
6

मेरे पास एक एनएसएमयूटेबलएरे है जिसमें कई ऑब्जेक्ट हैं।क्या होता है यदि एनएसएमयूटेबलएरे को एक ही समय में एकाधिक धागे द्वारा संशोधित किया जाता है? (यदि इसमें मौजूद वस्तुओं को कहीं और रखा गया है)

क्या होता है यदि सरणी में कोई परिवर्तन किया जाता है, जबकि मैं सरणी की एक प्रति बना रहा हूं [NSMutableArray arrayWithArray: someArray];

उदाहरण: यदि प्रतिलिपि बनाते समय किसी ऑब्जेक्ट को सरणी से हटा दिया जाता है?

मुझे यकीन नहीं है कि इस परिदृश्य का परीक्षण कैसे करें।

संपादित करें: ऑब्जेक्ट जारी नहीं किए जाते हैं (क्योंकि उन्हें कहीं और बनाए रखा जाता है)। मैं सिर्फ इस सरणी को लुकअप टेबल के रूप में उपयोग करता हूं।

+0

मुझे दो दिन पहले एक ही समस्या थी, लेकिन मैं एक सरणी से वस्तुओं को हटा रहा था और दूसरे में गणना कर रहा था। संशोधित सरणी के बारे में एक अपवाद मिला। यदि arrayWithArray: तेज़ गणना का उपयोग करता है (मुझे नहीं पता), यह एक अपवाद फेंक देगा। –

+0

मुझे लगता है कि आप मेरी समस्या को समझते हैं! मैं यह निर्धारित करने की कोशिश कर रहा हूं कि एक अपवाद फेंक दिया जाएगा या नहीं। लेकिन मैं इसे सत्यापित करने के लिए एक परीक्षण नहीं बना सकता क्योंकि मैं प्रतिलिपि बनाते समय सरणी को संशोधित करने के लिए एक और थ्रेड समन्वयित नहीं कर सकता। – xcoder

उत्तर

11

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

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

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

अद्यतन

... तो क्या होगा? प्रति (सभी 5 वस्तुओं होते हैं क्योंकि वे कहीं और वैसे भी बने रहते हैं? वे 4 शामिल है? (यहां तक ​​कि युक्त 4 मेरे लिए पर्याप्त है) अगर आप ठीक से संग्रह पहरा नहीं किया है, यह एक अपवाद फेंका है?

। अपरिभाषित व्यवहार के रूप में रूप में अच्छा है और आप भाग्यशाली हैं अगर यह दुर्घटनाओं

आप उचित सावधानी बरतने की अपरिभाषित व्यवहार से बचने की जरूरत अपने कार्यक्रम कि डोमेन काम कर रहा है जब यह उचित रूप से सुरक्षित नहीं है

विस्तृत करने के।।: वस्तुओं को बाहरी रूप से बनाए रखने से केवल अपरिभाषित व्यवहार \ ior की संभावना कम हो जाती है, लेकिन यह निश्चित रूप से इसे खत्म नहीं करती है। अधिक ई परिणामों के उदाहरणों में अपवाद, segfaults, पढ़ने या स्मृति लिखने शामिल हैं जो एक और सक्रिय आवंटन के रूप में प्रयोग किया जाता है (जो बहुत ही रहस्यमय मुद्दों के रूप में दिखाया जा सकता है जो पुनरुत्पादन के लिए लगभग असंभव हो सकता है)।

मैं आपको उचित रूप से सुरक्षा करने या एक और दृष्टिकोण लेने के लिए प्रोत्साहित करता हूं। यूबी EVIL है :)

+0

चूंकि किसी भी थ्रेड द्वारा ऑब्जेक्ट्स जारी नहीं किए जा रहे हैं, इसलिए मैं यह समझने की कोशिश कर रहा हूं कि क्या होता है यदि कोई सरणी संशोधित होती है, जबकि [NSMutableArray arrayWithArray: (NSMutableArray *)] चल रहा है। उदाहरण: 1. यदि मेरे पास एक सरणी है जिसमें 5 ऑब्जेक्ट्स हैं (कहीं और भी बनाए रखा गया है)। 2. एक और धागा इस सरणी की एक प्रति बनाने की कोशिश करता है। 3. एक तीसरा धागा मूल सरणी को संशोधित करता है (एक वस्तु को हटा देता है)। 4. क्या होता है? क्या प्रतिलिपि में सभी 5 ऑब्जेक्ट्स हैं (क्योंकि उन्हें कहीं और बनाए रखा जाता है? क्या उनमें 4 होते हैं? (यहां तक ​​कि 4 मेरे लिए भी पर्याप्त है) क्या एक अपवाद फेंक दिया गया है? – xcoder

+0

@xcoder – justin

+1

अपडेट किया गया बहुत बुरा मैं _undefined के लिए फिर से ऊपर नहीं जा सकता व्यवहार बुरा_ अद्यतन है। –

5

एप्पल के Docs से:

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

से

इसके अलावा एप्पल के Docs:

हालांकि "परमाणु" इसका मतलब है कि संपत्ति के लिए उपयोग धागा सुरक्षित है, बस अपने वर्ग परमाणु में सभी गुण बनाने मतलब यह नहीं है कि अपने वर्ग या अधिक आम तौर पर आपका ऑब्जेक्ट ग्राफ़ "थ्रेड-सुरक्षित" है- व्यक्तिगत एक्सेसर विधियों के स्तर पर प्रकाशित सुरक्षा व्यक्त नहीं की जा सकती है। मल्टीथ्रेडिंग के बारे में अधिक जानकारी के लिए, थ्रेडिंग प्रोग्रामिंग मार्गदर्शिका देखें।

+0

मैंने सेब दस्तावेज़ पढ़े हैं, लेकिन यह मेरे लिए अस्पष्ट है कि वास्तव में इस परिदृश्य में क्या होता है। चूंकि सिंक में संचालन करने के लिए दो थ्रेड प्राप्त करना मुश्किल है, इसलिए मैं नहीं देख सकता कि कौन सी समस्या होगी। – xcoder

+0

थ्रेडिंग प्रोग्रामिंग मार्गदर्शिका में "@ सिंक्रनाइज़ डायरेक्टिव का उपयोग करना" अनुभाग देखें। यह उत्तर भी देखें: http://stackoverflow.com/questions/3521190/synchronizing-nsmutablearray-for-thread-security – sosborn

+0

मुझे पता है कि @ सिंक्रनाइज़ेशन के लिए क्या उपयोग किया जाता है। मार्गदर्शिका बुरी चीजों के बारे में बात करती है जो तब हो सकती हैं जब किसी ऑब्जेक्ट को एक थ्रेड द्वारा एक्सेस किया जा रहा हो, किसी अन्य थ्रेड द्वारा जारी किया जाता है। चूंकि मेरी वस्तुओं को किसी भी थ्रेड द्वारा जारी नहीं किया जा रहा है, तो क्या होता है यदि किसी ऑब्जेक्ट के संदर्भ वाले सरणी को प्रतिलिपि बनाते समय संशोधित किया जाता है? मुझे नहीं लगता कि वहां एक "लटकते पॉइंटर" परिदृश्य हो सकता है, क्योंकि ऑब्जेक्ट्स को कहीं और बनाए रखा जाता है, इसलिए ऑब्जेक्ट को इंगित करने वाला कोई पॉइंटर वैध होना चाहिए। इस सरणी के साथ क्या होता है, अगर प्रतिलिपि बनाई जाती है तो इसे संशोधित किया जाता है? – xcoder

0

यदि निकालें ऑब्जेक्ट को उसी समय सरणीविथअरे के रूप में बुलाया जाता है, तो आपका प्रोग्राम क्रैश हो जाएगा। यदि आप सिंक्रनाइज़ेशन का उपयोग करते हैं, तो निकालें ऑब्जेक्ट को या तो सरणी विथअरे के ठीक पहले या बस करने के लिए मजबूर करना, आप नहीं जानते कि नई सरणी कितनी ऑब्जेक्ट्स होगी। वह तुरंत दुर्घटनाग्रस्त नहीं होगा, लेकिन आपका कोड क्या करने जा रहा है? आपको अपने दिमाग में बहुत स्पष्ट होना चाहिए कि [NSArray arrayWithArray: someArray] का परिणाम एक सरणी है जिसमें अभी कुछ आरे की सामग्री शामिल नहीं है, लेकिन अतीत में कुछ बिंदुओं पर कुछ ऐरे की सामग्री शामिल है।

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

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