10

Meine Anwendung verwendet GCD stark und fast alles wird in kleine Aufgaben aufgeteilt, die von Versendungen behandelt werden. Das zugrundeliegende Datenmodell wird jedoch meistens gelesen und nur gelegentlich geschrieben.Lesen-Schreiben-Sperre mit GCD

Ich verwende derzeit Sperren, um Änderungen an den kritischen Datenstrukturen beim Lesen zu verhindern. Aber nachdem ich heute ein paar mehr in Locks geschaut habe, habe ich NSConditionLock und einige Seiten über Lese-Schreib-Locks gefunden. Letzteres ist genau das, was ich brauche.

Ich fand diese Implementierung: http://cocoaheads.byu.edu/wiki/locks. Meine Frage ist, wird diese Implementierung mit GCD arbeiten, sehen Sie, dass es PThreads verwendet?

Antwort

20

Es wird immer noch funktionieren. Pthreads ist die Threading-API, die allen anderen threadverwendenden APIs unter Mac OS X zugrunde liegt. (Darunter gibt es Mach-Thread-Aktivierungen, aber das ist SPI, nicht API.) Die pthreads-Sperren erfordern jedoch nicht unbedingt pthreads Fäden.

Aber, GCD bietet eine bessere Alternative wie von iOS 5: dispatch_barrier_async(). Grundsätzlich haben Sie eine private Warteschlange für gleichzeitige Anrufe. Sie senden alle Leseoperationen auf die normale Weise an sie. Sie senden Schreiboperationen mit den Sperrroutinen an sie. Ta-da! Schreib-Lese-Verriegelung.

Sie können mehr darüber erfahren, wenn Sie Zugriff auf die WWDC 2011 session video for Session 210 - Mastering Grand Central Dispatch haben.

+1

Ah, ich hatte über die Barrieren gelesen, aber zu dieser Zeit konnte ich mir keine praktische Anwendung vorstellen (ich benutzte damals noch nie Multithreading) und vergaß alles über sie. Danke, ich werde versuchen zu sehen, ob ich das benutzen kann! –

+3

Mike Ash bietet auch ein schönes Beispiel für die Synchronisierung von Reader und Writer mit GCD. http://www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html –

1

Sie sollten auch eine serielle Warteschlange für alle Lese-/Schreibvorgänge in Betracht ziehen. Sie können dann dispatch_sync() schreibt in diese Warteschlange, um sicherzustellen, dass Änderungen an dem Datenmodell sofort angewendet werden und dispatch_async() alle liest, um sicherzustellen, dass Sie eine gute Leistung in der App beibehalten.

Da Sie eine einzige serielle Warteschlange haben, auf der alle Lese- und Schreibvorgänge stattfinden, stellen Sie sicher, dass während eines Schreibvorgangs keine Lesevorgänge stattfinden können. Dies ist viel weniger kostspielig als eine Sperre, aber es bedeutet, dass Sie mehrere Lesevorgänge nicht gleichzeitig ausführen können. Dies ist wahrscheinlich kein Problem für die meisten Anwendungen.

dispatch_barrier_async() verwenden könnte bedeuten, dass schreibt man eine beliebige Menge an Zeit dauern, tatsächlich begangen werden, da alle bereits vorhandene Aufgaben in der Warteschlange vor Ihrer Barriere Block ausgeführt abgeschlossen werden müssen.

+0

Hmm, ich wusste nicht einmal Async-Versand war in einer seriellen Warteschlange möglich. Das hört sich nach einer interessanten Idee an ... Alle Lesevorgänge sind relativ kleine Bearbeitungen, obwohl Schreiben normalerweise das Lesen, Bearbeiten und anschließende Speichern der Daten bedeutet. –

+5

Normalerweise machen Sie das Gegenteil von dem, was hier vorgeschlagen wird. Lesevorgänge müssen normalerweise synchron übermittelt werden, da Sie oft das Ergebnis haben müssen, bevor Sie zum Anrufer zurückkehren. Schreibvorgänge können asynchron ausgeführt werden, da der Aufrufer nur darauf achtet, dass der von außen beobachtbare Zustand mit dem Datum übereinstimmt, das geschrieben wurde. Dies liegt daran, dass kein Lesevorgang fortgesetzt werden kann, bis der Schreibvorgang abgeschlossen ist, da die Warteschlange seriell ist. Es hilft nicht mit mehreren Lesern, wie bereits erwähnt. –