2012-04-06 14 views
5

İşte örnek kod Aşağıda http://developer.apple.com/library/ios/#samplecode/MVCNetworking/Introduction/Intro.htmlApple'ın Sample MVCNetworking'deki Singleton Sınıfı NetworkManager doğru mu?

link 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; 
} 

Açıkçası burada iş parçacığı güvenli sorunları vardır dosyadan kod parçacığı olmasıdır. Birden fazla iş parçacığı olduğunda iki NetworkManager örneği oluşturulabilir. Yani Apple bir hata yaptı, değil mi?

+0

"Açıkça iki sNetworkManager oluşturulabilir. Bu yüzden Apple bir hata yaptı, değil mi?" Niye ya? –

+0

Lütfen Kurt'un cevabına bir bakın. –

cevap

1

Evet, yanlış. sNetworkManager ile nil ile başlayın ve iki konu T1 ve T2'yi düşünün. mümkün

Bir

, olası ise, senaryodur:

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 bunu yapmanın bazı daha güvenli yolları vardır.

0

Bu kodda hata yok. "Statik" kelimesinin kullanılmasının basit bir nedeni için sadece bir sNetworkManager oluşturulmuştur. Statik anahtar kelime, değişkeni global olarak tanımlamak için kullanılır, ancak yalnızca bu işlev için görünür. Değişken + (NetworkManager *) sharedManager'ın ilk çağrısında ayrılır, daha sonra sıfırlanacak ve daha fazla başlatılamaz.

+0

Merhaba Guy, Kurt'un cevabına bir bakın, eğer Kurt'un analizinin doğru olmadığını düşünüyorsanız lütfen yorumlarınızı ekleyebilir misiniz? –

+0

Onun analizi doğrudur, ancak bu senaryonun gerçekleşmesi olası değildir. İlk mesajınızda bu iş parçacığı hatası hakkında konuşur musunuz? "Statik" anahtar kelime hakkında konuştuğunu sanıyordum. – user1316852

2

Evet, haklısınız. Eşzamanlılık ortamında sorun yaşayacak. Daha iyi bir yol alloc önce çift kontrol kullanıyor:

BobCromwell haklı What should my Objective-C singleton look like?

Güncelleme:

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

Ve Ojbective-C kullanarak tekil yazmak için yol bir sürü, bu yayını kontrol . double check lock elma en Threading Programming Guide yılında, elma belgeyi önerilmez:

bir kez kontrol edilecek kilit kilit alarak önce kilitleme kriterlerini test ederek bir kilit alma yükünü azaltmak için bir girişimdir. Çift denetimli kilitler potansiyel olarak güvensiz olduğundan, sistem bunlara açık destek sağlamamaktadır ve bunların kullanımı önerilmez. '

+0

Çift kontrol kilidinin doğru olmadığını ve hem iOS hem de Mac'te desteklenmediğini düşünüyorum. –

+0

@BobCromwell Neden? Bana bir neden veya referans verebilir misiniz? Basit kelimelerle – tangqiaoboy

+1

, sNetwokManager, nesne tamamen başlatılmadan önce sıfır olamaz. Lütfen Apple'ın "Threading Programming Guide" belgesindeki Double-checkedlock'u arayın ve bu konuyla ilgili bir yazı yayınlayın: http://www.wincent.com/a/knowledge-base/archives/2006/01/locking_doublec.php –