2017-10-05 15 views
1

essayant de faire du fil tableau sécurisé mais il fonctionne pas comme je m'y attendaisDispatchQueue barrière question

import Foundation 
import PlaygroundSupport 

PlaygroundPage.current.needsIndefiniteExecution = true 

public class SafeArray<Element> { 
    private var array = [Element]() 
    private let queue = DispatchQueue(label: "queueBarrier", attributes: .concurrent) 

    public func append(element: Element) { 
     queue.async(flags: .barrier) { 
      self.array.append(element) 
     } 
    } 

    public var elements: [Element] { 
     var result = [Element]() 
     queue.sync { 
      result = self.array 
     } 
     return result 
    } 

    public var last: Element? { 
     var result: Element? 
     queue.sync { 
      result = self.array.last 
     } 
     return result 
    } 
} 




var safeArray = SafeArray<Int>() 
var array = Array<Int>() 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = array.last ?? 0 
    array.append(last + 1) 
    print("array = [..\(last)]") 
} 

print(array) 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = safeArray.last ?? 0 
    safeArray.append(element: last + 1) 
     print("safeArray = [..\(last)]") 
} 

print(safeArray.elements) 

output of my code

Je prévu ce tableau devrait avoir un certain désordre, mais SafeArray devrait avoir des chiffres de 0 à 9.

Je comprends que tableau ont 3 valeurs, mais safeArray a 10 valeurs comme prévu. Mais pourquoi cette valeur ne va pas de 0 à 9?

Merci!

Répondre

0

Non Vous n'obtiendrez la valeur sous forme 1 - 10 !!!, En raison de DispatchQueue.concurrentPerform effectuer des opérations multiples en même temps

Laissez-moi vous expliquer

On suppose que DispatchQueue.concurrentPerform exécutera 3 articles en même temps, puis ici

let last = safeArray.last ?? 0 

Vous obtiendrez 0 Trois fois mais il est annexant tableau en ajoutant 1 si

votre tableau devient quelque chose comme [1,1,1 ...]

Il n'y a pas de rôle de barrie ici dans la production encore je Clearing que

Les lecteurs seront toujours bloqués lorsqu'un processus de barrière est en cours d'exécution. Même s'il y a plusieurs blocs de lecture déjà en cours d'exécution en parallèle, le processus barrière attendra tous les lecteurs à terminer avant de commencer l'écriture

Si vous avez besoin le comportement de blocage, vous devez utiliser DispatchSemaphore comme MjZac expliqué

J'espère que c'est clair pour vous

0

Pourquoi ne pas utiliser DispatchSemaphore?

import Foundation 
import PlaygroundSupport 

PlaygroundPage.current.needsIndefiniteExecution = true 

public class SafeArray<Element> { 
    private var array = [Element]() 
    private let semaphore = DispatchSemaphore(value: 1) 
    private var lastEl: Element? 

    public func append(element: Element) { 

      self.array.append(element) 
    } 

    public var elements: [Element] { 
     var result = [Element]() 
     result = self.array 
     return result 
    } 

    public var last: Element? { 
     self.semaphore.wait() 
     lastEl = self.array.last 
     self.semaphore.signal() 
     return lastEl 
    } 
} 




var safeArray = SafeArray<Int>() 
var array = Array<Int>() 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = array.last ?? 0 
    array.append(last + 1) 
    print("array = [..\(last)]") 
} 

print(array) 

DispatchQueue.concurrentPerform(iterations: 10) { (int) in 
    let last = safeArray.last ?? 0 
    safeArray.append(element: last + 1) 
    print("safeArray = [..\(last)]") 
} 

print(safeArray.elements)