2017-10-02 8 views
1

J'ai le code suivant, qui à mon sens devrait fournir une lecture thread-safe et écrire sur _predictions. Mon isolationQueue est une file d'attente concurrente et doit rester en tant que telle. J'appelle plusieurs opérations asynchrones indépendantes sur cette file d'attente pour calculer des prédictions pour diverses images. Le seul élément partagé entre les différents appels est le moment où la prédiction est définie. Toutefois, pour certaines raisons, l'assainisseur de fil semble détecter une condition de concurrence entre le getter et le setter.Condition de course sur une synchronisation de file d'attente simultanée personnalisée pour getter et setter

enter image description here enter image description here

Suis-je manque quelque chose?

+1

Comment est définie la propriété isolationQueue? Est-ce une file d'attente d'expédition * serial *? –

+0

a mis à jour la question. c'est global donc je crois que ce serait simultané. 'var isolationQueue = DispatchQueue.global (qos: .default)' –

Répondre

1

Les files d'attente de répartition globales sont et les files d'attente simultanées, elles ne peuvent donc pas être utilisées pour protéger contre l'accès simultané d'une ressource.

Vous devez définir votre propre file d'attente série d'expédition à cette fin:

var isolationQueue = DispatchQueue(label: "my.queue.identifier") 
+0

L'utilisation de 'sync' ne protège pas contre les autres threads accédant aux ressources alors qu'il est exécuté dans une file d'attente concurrente? Y at-il de toute façon pour assurer l'accès en série sur une file d'attente concurrente? –

+0

@RezaShirazian: 'sync' signifie que le thread appelant attend sa fin, mais que les blocs envoyés à partir de threads différents peuvent s'exécuter simultanément. Voici un bon aperçu des 4 combinaisons possibles: https://stackoverflow.com/questions/19179358/concurrent-vs-serial-queues-in-gcd. –

+0

qu'est-ce que je fais avec le 'sync' alors? si mon 'isolationQueue' est en série' sync' ne semble pas très logique dans ce cas. –

0

Pour votre cas, en utilisant DispatchSemaphore() est plus simple et a moins de frais généraux. Le code ressemble

var isolationSem = DispatchSemaphore(value: 1) 
var _predictions: [Int:[Prediction]] = [:] 

var predictions:[Int: [Prediction]] { 
    get { 
    var result: [Int: [Prediction]]! 
    isolationSem.wait() 
    result = _predictions 
    isolationSem.signal() 
    return result 
    } 
    set(value) { 
    isolationSem.wait() 
    self._predictions = value 
    isolationSem.signal() 
    } 
} 

Voir this pour le cas où DispatchSemaphore ne convient pas.