2015-04-22 19 views
12

Aşağıdaki kodu vardır: adı senkronize olmayan, işlem, giriş parametresini gösterir ve tamamlandığında olarak, Bu durumda,C# gibi Swift bir nesne kilitleme herhangi bir şekilde var

func foo() { 
    var sum = 0 
    var pendingElements = 10 

    for i in 0 ..< 10 { 
     proccessElementAsync(i) { value in 
      sum += value 
      pendingElements-- 

      if pendingElements == 0 { 
       println(sum) 
      } 
     } 
    } 
} 

fonksiyonu proccessElementAsync ilgili tamamlama işleyicisini çağırır.

Bu yaklaşımın vermiş olduğu rahatsızlık, pendingElements değişkeninin birden çok iş parçacığı aracılığıyla erişilebilmesi nedeniyle if pendingElements == 0 ifadesinin hiçbir zaman doğru değere sahip olmamasıdır. C# '

biz böyle bir şey yapabilir:

Object lockObject = new Object(); 
... 

lock (lockObject) { 
    pendingElements--; 

    if (pendingElements == 0) { 
     Console.WriteLine(sum); 
    } 
} 

ve bu değişken aynı anda sadece bir iş parçacığı için erişilebilir olmasını sağlar. Swift'de aynı davranışı elde etmenin bir yolu var mı?

+2

https://www.mikeash.com/pyblog/friday-qa-2015-02-06-locks-thread-safety-and-swift.html –

+0

Yan not: C# 'kilit (someIntValue) 'Neyi başarmaya çalıştığınıza uzaktan yakın bir şey yapmaz ... C# 'da lütfen sadece kilitleme için özel nesneler oluşturma varsayılan kılavuzunu takip etmeyi düşünün ... –

+1

C# ile biz' Interlocked.Decrement ' – Bas

cevap

11

Bu yardımcı olur umarım.

func lock(obj: AnyObject, blk:() ->()) { 
    objc_sync_enter(obj) 
    blk() 
    objc_sync_exit(obj) 
} 

var pendingElements = 10 

func foo() { 
    var sum = 0 
    var pendingElements = 10 

    for i in 0 ..< 10 { 
     proccessElementAsync(i) { value in 

      lock(pendingElements) { 
       sum += value 
       pendingElements-- 

       if pendingElements == 0 { 
        println(sum) 
       } 
      } 

     } 
    } 
} 
+0

Cevabınız için teşekkür ederiz. Eğer objc_sync_enter (obj) ve objc_sync_exit çağrıları inandığım şeyi yaparsa, cevabınız benim problemimi çözer. Cevabınıza, bu işlevlerin neler yaptığıyla ilgili bazı ayrıntılar ekleyebilir misiniz? Bunun, cevabın kalitesini artıracağını düşünüyorum. –

+0

, objc_sync_enter bilgisini aldım ve Apple'ın belgesinden çıktım. objc_sync_enter (id obj) : 'obj' üzerinde senkronizasyona başlayın. Gerekirse 'obj' ile ilişkilendirilmiş yinelemeli pthread_mutex'i ayırır. int objc_sync_exit (id obj): 'obj' ile senkronizasyonu sonlandır. –

+1

sadece diğerleri için, daha sağlam bir versiyonu önermek 'func synchronized (object: AnyObject!, @noescape _ kapatma:() atıyor ->()) rethrows { objc_sync_enter (nesne) erteleme { objc_sync_exit (nesne) } deneyin kapatma() } ' –

4

hiçbir yerli kilitleme araçları vardır, ama bu SO söz açıklandığı gibi geçici çözümler vardır:

func synchronize(lockObj: AnyObject!, closure:()->()){ 
     objc_sync_enter(lockObj) 
     closure() 
     objc_sync_exit(lockObj) 
    } 

: cevaplar birini kullanarak

What is the Swift equivalent to Objective-C's "@synchronized"?

, bir işlev oluşturabilirsiniz ve sonra:

 func foo() { 
     var sum = 0 
     var pendingElements = 10 

     for i in 0 ..< 10 { 
      processElementAsync(i) { value in 

       synchronize(pendingElements) { 
        sum += value 
        pendingElements-- 

        if pendingElements == 0 { 
         println(sum) 
        } 
       } 

      } 
     } 
    } 
İlgili konular