10

La mia applicazione fa un uso pesante di GCD e quasi tutto è suddiviso in piccole attività gestite da dispacci. Tuttavia, il modello di dati sottostante è principalmente letto e solo occasionalmente scritto.Blocco lettura-scrittura con GCD

Attualmente utilizzo blocchi per impedire modifiche alle strutture di dati critiche durante la lettura. Ma dopo aver esaminato i blocchi ancora oggi, ho trovato NSConditionLock e qualche pagina sui blocchi di lettura-scrittura. Quest'ultimo è esattamente ciò di cui ho bisogno.

Ho trovato questa implementazione: http://cocoaheads.byu.edu/wiki/locks. La mia domanda è: questa implementazione funzionerà con GCD, visto che usa PThreads?

risposta

20

Funzionerà ancora. pthreads è l'API di threading che sta alla base di tutte le altre API che usano thread su Mac OS X. (Sotto c'è l'attivazione del thread Mach, ma questo è SPI, non API.) Comunque, i lock pthreads non richiedono realmente l'uso di pthreads filettature.

Tuttavia, GCD offre un'alternativa migliore a partire da iOS 5: dispatch_barrier_async(). Fondamentalmente, hai una coda concorrente privata. Inviate tutte le operazioni di lettura ad esso nel modo normale. Sottoponi le operazioni di scrittura usando le routine di barriera. Ta-da! Blocco lettura-scrittura.

È possibile ottenere ulteriori informazioni a riguardo se si ha accesso allo WWDC 2011 session video for Session 210 - Mastering Grand Central Dispatch.

+1

Ah, avevo letto delle barriere, ma al momento non riuscivo a pensare ad un'applicazione pratica (ho usato a malapena il multithreading allora) e ho dimenticato tutto di loro. Grazie, proverò a vedere se posso usarlo! –

+3

Mike Ash fornisce anche un buon esempio di come eseguire la sincronizzazione lettore-scrittore tramite GCD. http://www.mikeash.com/pyblog/friday-qa-2011-10-14-whats-new-in-gcd.html –

1

Si potrebbe anche voler considerare di mantenere una coda seriale per tutte le operazioni di lettura/scrittura. È quindi possibile scrivere dispatch_sync() in quella coda per garantire che le modifiche al modello di dati vengano applicate tempestivamente e dispatch_async() tutte le letture per assicurarsi di mantenere buone prestazioni nell'app.

Poiché si dispone di una singola coda seriale su cui si svolgono tutte le letture e le scritture, si garantisce che non si verifichino letture durante una scrittura. Questo è molto meno costoso di un blocco ma significa che non è possibile eseguire più operazioni di "lettura" contemporaneamente. È improbabile che questo causi un problema per la maggior parte delle applicazioni.

L'utilizzo di dispatch_barrier_async() può significare che le scritture effettuate richiedono una quantità arbitraria di tempo per essere effettivamente impegnate poiché tutte le attività preesistenti nella coda devono essere completate prima dell'esecuzione del blocco di barriera.

+0

Hmm, non mi ero nemmeno reso conto che la distribuzione asincrona fosse possibile su una coda seriale. Sembra un'idea interessante ... Tutte le letture sono modifiche ragionevolmente piccole, anche se le scritture di solito significano leggere, modificare e quindi salvare di nuovo i dati. –

+5

Di solito, fai il contrario di quanto suggerito qui. Normalmente le letture devono essere inviate in modo sincrono, poiché spesso è necessario avere il risultato prima di tornare al chiamante. Le scritture possono essere eseguite in modo asincrono, poiché il chiamante si preoccupa solo che lo stato osservabile dall'esterno sia coerente con la data in cui è stata scritta, il che è dovuto al fatto che nessuna lettura può procedere finché la scrittura non è completata perché la coda è seriale. Non aiuta con più lettori, come notato. –