2013-06-13 13 views
6

उद्देश्य सी में मैं विभिन्न थ्रेड से एनएसएमयूटेबलएरे उदाहरण का उपयोग कर रहा हूं और मैं इसे थ्रेड सुरक्षित बनाने के लिए @ सिंक्रनाइज़ का उपयोग कर रहा हूं। वर्तमान में इस सरणी में मेरे सभी acces @synchronized ब्लॉक से सुरक्षित हैं, यहां तक ​​कि objectAtIndex: method। फिर भी मुझे आश्चर्य है कि कौन सी विधियों को वास्तव में @ सिंक्रनाइज़ के साथ संरक्षित करने की आवश्यकता है। क्या मुझे पढ़ने की पहुंच की रक्षा करने की ज़रूरत है?एनएसएमयूटेबलएरे संग्रह और @ सिंक्रनाइज़ किए गए ब्लॉक

क्या होगा यदि 'ऑब्जेक्टएट इंडेक्स' सुरक्षित नहीं है और उसी समय 'removeObject' कहा जाता है?

यदि सभी विधियों को @synchronized द्वारा संरक्षित किया गया है तो प्रदर्शन के बारे में क्या? (मैं एक टीसीपी/udp गेम सर्वर लिख रहा हूं और वास्तव में इन सरणी को अधिक से अधिक नहीं करना चाहता हूं अगर यह perf कम करेगा या ताले उत्पन्न करेगा)।

उदाहरण के लिए मुझे लगता है कि 'includeObject:' विधि ऑब्जेक्ट को खोजने के लिए गणना करेगी और मुझे किसी अन्य थ्रेड में 'removeObject:' को एक कॉन्सूरेंट कॉल से बचना चाहिए।

शायद एक अच्छा समाधान भी अलग ताले है (पढ़ने के लिए और लिखने) के लिए होगा ...

सहायता और सुझाव का स्वागत है!

बहुत बहुत धन्यवाद।

कृपया एक नमूना कोड नीचे वर्णन करने के लिए लगता है:

@interface TestClass : NSObject 
{ 
    NSMutableArray * array; 
} 

@end 

@implementation TestClass 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     array = [NSMutableArray array]; 
    } 
    return self; 
} 

-(id)objectAtIndex:(NSUInteger)index 
{ 
    @synchronized(array) **// IS IT USEFUL OR NOT ??** 
    { 
     return [array objectAtIndex:index]; 
    } 
} 

-(void)removeObject:(id)object 
{ 
    @synchronized(array) 
    { 
     [array removeObject:object]; 
    } 
} 

-(void)compute 
{ 
    @synchronized(array) 
    { 
     for (id object in array) 
     { 
      [object compute]; 
     } 
    } 
} 

@end 

उत्तर

5

हाँ, आप पढ़ सकते हैं सिंक्रनाइज़ करने के लिए उन्हें उत्परिवर्तन से एक साथ होने से रोकने के लिए एक्सेस करता है। पढ़ें, अन्य पढ़ने के उपयोग के साथ एक्सेस सुरक्षित रूप से एक साथ चल सकते हैं।

यदि आपके पास एकाधिक पाठक हैं, तो यह एक पठन-लेखन लॉकिंग योजना की जांच करने योग्य है। आप पर्थ्रेड रीड-राइट लॉक का उपयोग कर सकते हैं (यानी pthread_rwlock_...())।

वैकल्पिक रूप से, आप "बाधा" दिनचर्या के साथ ओएस एक्स 10.7+ और आईओएस 5+ पर जीसीडी का उपयोग कर सकते हैं। एक निजी समवर्ती कतार बनाएँ। सामान्य फैशन में सभी पढ़ने के लिए इसे सबमिट करें (उदा। dispatch_sync())। dispatch_barrier_async() जैसे बाधा दिनचर्या का उपयोग करके उत्परिवर्तन संचालन सबमिट करें। (यह असीमित हो सकता है क्योंकि आपको आम तौर पर यह जानने की आवश्यकता नहीं है कि उत्परिवर्तन जारी रखने से पहले पूरा हो गया है। आपको केवल यह जानना होगा कि उत्परिवर्तन जमा करने के बाद सबमिट किए गए सभी पढ़े उत्परिवर्तन के परिणाम देखेंगे, और अवरोध गारंटी देता है।)

यदि आपके पास WWDC 2011 session video for Session 210 - Mastering Grand Central Dispatch तक पहुंच है तो आप इसके बारे में अधिक जान सकते हैं।

+0

मुझे वास्तव में जीसीडी समाधान पसंद है। चूंकि मैं कई म्यूटेबल सरणी (और शब्दकोश भी) का उपयोग कर रहा हूं, जिसे मैं संरक्षित करना चाहता हूं, मुझे आश्चर्य है कि क्या मैं अपना खुद का जीसीडीएमटेबलएरे और जीसीडीएमटेबल डिक्शनरी बना सकता हूं जो सभी विधियों को ओवरराइड करेगा और सरणी या शब्दकोश के प्रत्येक उदाहरण के लिए dispatch_queue_t जोड़ देगा। लेकिन क्या यह 10 विवादास्पद शब्दकोश अपने स्वयं के प्रेषण_क्यू के साथ एक अच्छा समाधान है? और प्रत्येक उदाहरण में एक अलग कतार बनाने के लिए? dispatch_queue_create एक नाम के रूप में नाम ले लो, इस नाम को कैसे उत्पन्न करें? शायद इस तरह की संरक्षित सरणी और dict पहले ही लिखा गया है ... लेकिन कुछ भी नहीं मिला। –

+0

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

0

आपको यह पता होना चाहिए कि आप जो कर रहे हैं वह वास्तव में बहुत मदद नहीं कर रहा है। उदाहरण के लिए, यदि आपके सरणी में दस तत्व हैं और आप [myObject objectAtIndex: 9] को कॉल करते हैं, जबकि एक अन्य थ्रेड [myObject removeObject: someObject] को कॉल करता है, तो संभावना है कि पहला कॉल एक सरणी तत्व तक पहुंचता है जो अब मौजूद नहीं है और अपवाद फेंकता है ।

objectAtIndex वास्तव में उपयोगी नहीं है अगर अन्य धागे वस्तुओं को हटा या सम्मिलित कर सकते हैं।

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