2016-07-14 7 views
5

Ich sah in diesem Jahr WWDC GCD reden in letzter Zeit, und ich denke, es gibt ein Code-Schnipsel, mit dem etwas nicht stimmt. Es geht darum, eine Eigenschaft Thread-Safe mit DispatchQueues.Synchronisieren Eigenschaften in Swift 3 mit GCD

class MyObject { 
    private var internalState: Int 
    private let internalQueue: DispatchQueue // Serial or Concurrent? 

    var state: Int { 
     get { 
      return internalQueue.sync { internalState } 
     } 

     set (newState) { 
      internalQueue.sync { internalState = newState } 
     } 
    } 
} 

Sie verwenden eine DispatchQueue eine Eigenschaft zu sperren. Aber ich denke, dieses Snippet ist nicht gültig, weil die internalQueue gleichzeitig sein könnte. Also, wenn wir den Setter von zwei verschiedenen DispatchQueues/Threads aufrufen, wenn diese interne Warteschlange nicht seriell ist, könnte es auch zu Threading-Problemen führen, oder? Weil in meinem Verständnis sync nur den aufrufenden Thread enthält und fortfährt, wenn die Aufgabe abgeschlossen ist. Was denkst du über dieses Snippet? Liege ich falsch?

+4

Ja, Sie würden internalQueue als * serielle * Dispatch-Warteschlange definieren. –

Antwort

6

Aber ich denke, das Snippet nicht gültig ist, weil die internalQueue

gleichzeitig sein könnte, aber es ist nicht gleichzeitig. Von Ihnen erstellte Versandwarteschlangen sind standardmäßig seriell. Das ist der Sinn der Technik (und des Beispiels).

+0

Vielleicht möchten Sie WWDC-Videos auf GCD aus früheren Jahren sehen. Sie sind in diesem Punkt klarer. – matt

+0

Danke Matt, das wusste ich nicht. –

7

Ich möchte nur einen anderen Ansatz zeigen, der es Ihnen ermöglicht, gleichzeitig zu lesen, aber während des Schreibens alles blockiert, indem Sie eine Dispatch-Barriere verwenden.

class MyObject { 
private var internalState: Int 
private let internalQueue = DispatchQueue(label: "reader-writer", attributes: .concurrent)) 

var state: Int { 
    get { 
     return internalQueue.sync { internalState } 
    } 

    set (newState) { 
     internalQueue.async(flags: .barrier) { internalState = newState } 
    } 
    } 
} 

Mit diesem Ansatz können gleichzeitig in der Warteschlange liest auftreten, aber schreibt ausschließlich ausgeführt werden, aufgrund der Barriere.

Dies ist nur eine Swift 3-Konvertierung eines Ansatzes, der in dem Buch Effektives Ziel C 2.0, geschrieben von Matt Galloway, erklärt wird.

+1

Schön. Hier könnte auch eine private gleichzeitige Warteschlange verwendet werden. –

+0

[Diese Frage] (http://stackoverflow.com/q/38084482/819340) bietet mehr Kontext für die Option ".barrier". –

+0

@Rob danke, ich werde jetzt reparieren. – Andrea