2012-02-02 9 views
295

ARC kapsamında tek birtonun paylaşılan örnek erişimcisinde dispatch_once kullanılmasının nedeni nedir?Apple neden ARC kapsamında singleton şablonunu uygulamak için dispatch_once kullanılmasını önerir?

+ (MyClass *)sharedInstance 
{ 
    // Static local predicate must be initialized to 0 
    static MyClass *sharedInstance = nil; 
    static dispatch_once_t onceToken = 0; 
    dispatch_once(&onceToken, ^{ 
     sharedInstance = [[MyClass alloc] init]; 
     // Do any other initialisation stuff here 
    }); 
    return sharedInstance; 
} 

Tektonu arka planda eşzamansız olarak başlatmak kötü bir fikir değil mi? Paylaşılan örneği talep edip hemen ona güvenirsem ne olur, ama dispatch_once benim nesneyi oluşturmak için Noel'e kadar sürer? Hemen geri dönmez mi? En azından bu, Grand Central Dispatch'in bütün noktası gibi görünüyor.

Peki neden bunu yapıyorlar?

+0

'Not: statik ve genel değişkenler varsayılan olarak sıfırdır. – ikkentim

cevap

406

dispatch_once() kesinlikle senkronize edilmiştir. GCD yöntemlerinin tümü eşzamansız bir şey yapmaz (nokta, dispatch_sync() eşzamanlıdır).

+ (MyClass *)sharedInstance { 
    static MyClass *sharedInstance; 
    @synchronized(self) { 
     if (sharedInstance == nil) { 
      sharedInstance = [[MyClass alloc] init]; 
     } 
    } 
    return sharedInstance; 
} 

bunun üzerinde dispatch_once() yararı daha hızlı olmasıdır: dispatch_once() kullanımı aşağıdaki deyim değiştirir. Aynı zamanda semantik olarak daha temizdir, çünkü aynı zamanda birden fazla iş parçacığından sizi paydaşlığınızın tahsis edilmesini engeller - eğer hepsi aynı zamanda denerse. İki örneğin oluşturulmasına izin vermez. dispatch_once()'un tüm fikri, "yaptığımız şeyleri tam olarak bir kez ve yalnızca bir kez gerçekleştirir".

+4

Argümanın hatırı sayılırda şunu belirtmem gerekir: [belgeler] (https://developer.apple.com/library/mac/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/ func/dispatch_once) eşzamanlı olarak çalıştırıldığını söylemiyor. Sadece birden fazla eşzamanlı çağrının serileştirileceğini söylüyor. – expert

+5

Daha hızlı olduğunu iddia ediyorsunuz - ne kadar hızlı? Doğruyu söylemediğini düşünmek için hiçbir nedenim yok, ama basit bir kıyaslama görmek istiyorum. –

+29

Sadece basit bir kıyaslama yaptım (iPhone 5'de) ve dispatch_once'ın @synchronized'den 2x daha hızlı olduğu anlaşılıyor. –

39

Çünkü yalnızca bir kez çalışır. Bu yüzden, farklı konulardan iki kez erişmeye çalışırsanız, bir soruna neden olmaz.

Mike Ash, Care and Feeding of Singletons blog yayınının tam bir tanımı vardır.

Tüm GCD blokları eşzamansız olarak çalıştırılmaz.

+11

Kevin'ın daha iyi bir yanıtı var, ama Mike Ash'ın gönderdiği bağlantıyı tutmak için benimkini bırakıyorum. – Abizern