2012-04-06 6 views
5

यहाँ नमूना कोड http://developer.apple.com/library/ios/#samplecode/MVCNetworking/Introduction/Intro.htmlऐप्पल के नमूना एमवीसीनेटवर्किंग में सिंगलटन क्लास नेटवर्क मैनेजर सही है?

नीचे के लिए लिंक फ़ाइल NetworkManager.m

+ (NetworkManager *)sharedManager 
// See comment in header. 
{ 
    static NetworkManager * sNetworkManager; 

    // This can be called on any thread, so we synchronise. We only do this in 
    // the sNetworkManager case because, once sNetworkManager goes non-nil, it can 
    // never go nil again. 

    if (sNetworkManager == nil) { 
     @synchronized (self) { 
      sNetworkManager = [[NetworkManager alloc] init]; 
      assert(sNetworkManager != nil); 
     } 
    } 
    return sNetworkManager; 
} 

जाहिर है धागा सुरक्षित मुद्दों यहाँ हैं से कोड का टुकड़ा है। एक से अधिक धागे होने पर दो NetworkManager उदाहरण बनाया जा सकता है। तो ऐप्पल ने गलती की, है ना?

+0

"स्पष्ट रूप से दो एसनेटवर्क प्रबंधक बनाया जा सकता है। इसलिए ऐप्पल ने गलती की, है ना?" क्यूं कर? –

+0

कृपया कर्ट के उत्तर पर एक नज़र डालें। –

उत्तर

1

हाँ, यह गलत है। के साथ nil के साथ शुरू करें, और दो धागे टी 1 और टी 2 पर विचार करें।

एक संभव, संभावना नहीं है, परिदृश्य है:

T1: Determines (sNetworkManager == nil) is true 
T2: Determines (sNetworkManager == nil) is true 
T1: Takes the @synchronized lock 
    Creates a NetworkManager 
    Sets sNetworkManager 
    Releases the lock 
T2: Takes the @synchronized lock 
    Creates a NetworkManager 
    Sets sNetworkManager, LEAKING the first one 
    Releases the lock 

This question यह कर में से कुछ को सुरक्षित तरीके हैं।

0

इस कोड में कोई गलती नहीं है। केवल एक sNetworkManager सरल कारण के लिए बनाया गया है कि "स्थिर" शब्द का उपयोग किया जाता है। वैरिएबल कीवर्ड को वैरिएबल को ग्लोबल के रूप में परिभाषित करने के लिए यहां उपयोग किया जाता है लेकिन केवल उस फ़ंक्शन के लिए दृश्यमान होता है। परिवर्तनीय को + (NetworkManager *) साझा प्रबंधक के पहले कॉल में आवंटित किया गया है, फिर यह शून्य नहीं है और अब और प्रारंभ नहीं किया गया है।

+0

हाय गाय, कर्ट के जवाब पर एक नज़र डालें, अगर आप सोचते हैं कि कर्ट का विश्लेषण सही नहीं है तो कृपया अपनी टिप्पणियां जोड़ें। –

+0

उनका विश्लेषण सच है लेकिन यह संभावना नहीं है कि यह परिदृश्य होता है। क्या आप अपने पहले संदेश में इस धागे की सुरक्षित गलती के बारे में बात करेंगे? मैंने सोचा कि आप "स्थैतिक" कीवर्ड के बारे में बात करते हैं। – user1316852

2

हाँ, आप सही हैं। यह समवर्ती पर्यावरण में समस्या होगी। एक बेहतर तरीका alloc से पहले दोहरी जांच उपयोग कर रहा है:

+ (NetworkManager *)sharedManager 
{ 
    static NetworkManager * sNetworkManager; 
    if (sNetworkManager == nil) { 
     @synchronized (self) { 
      if (sNetworkManager == nil) { 
       sNetworkManager = [[NetworkManager alloc] init]; 
       assert(sNetworkManager != nil); 
      } 
     } 
    } 
    return sNetworkManager; 
} 

और वहाँ सिंगलटन Ojbective-सी का उपयोग कर लिखने के लिए जिस तरह से के बहुत सारे हैं, इस पोस्ट की जाँच करें: What should my Objective-C singleton look like?

अद्यतन

BobCromwell सही है । double check lock सेब द्वारा सिफारिश की है नहीं, दस्तावेज़ सेब के Threading Programming Guide में:

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

+0

मुझे लगता है कि डबल चेक लॉक सही नहीं है और आईओएस दोनों मैक पर समर्थित नहीं है। –

+0

@BobCromwell क्यों? क्या आप मुझे कुछ कारण या संदर्भ दे सकते हैं? – tangqiaoboy

+1

सरल शब्दों में, ऑब्जेक्ट पूरी तरह से init-ed से पहले sNetwokManager शून्य नहीं हो सकता है। कृपया ऐप्पल के दस्तावेज़ "थ्रेडिंग प्रोग्रामिंग गाइड" में डबल-चेकलॉक खोजें और यहां इस बारे में एक पोस्ट है: http://www.wincent.com/a/knowledge-base/archives/2006/01/locking_doublec.php –

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