2013-02-06 18 views
7

Essenzialmente, ho un set di dati in un NSDictionary, ma per comodità sto impostando alcuni NSArray s con i dati ordinati e filtrati in diversi modi. I dati arriveranno attraverso diversi thread (blocchi) e voglio assicurarmi che ci sia un solo blocco alla volta che modifica il mio data store.blocco @synchronized GCD dispatch_async()

Ho passato la briga di creare una coda di spedizione questo pomeriggio, e poi casualmente sono incappato in un post su @synchronized che mi ha fatto sembrare esattamente quello che voglio fare esattamente.

Quindi ciò che ho in questo momento è ...

// a property on my object 
@property (assign) dispatch_queue_t matchSortingQueue; 

// in my object init 
_sortingQueue = dispatch_queue_create("com.asdf.matchSortingQueue", NULL); 

// then later... 
- (void)sortArrayIntoLocalStore:(NSArray*)matches 
{ 
    dispatch_async(_sortingQueue, ^{ 
     // do stuff... 
    }); 
} 

E la mia domanda è, posso solo sostituire tutto questo con il seguente?

- (void)sortArrayIntoLocalStore:(NSArray*)matches 
{ 
    @synchronized (self) { 
     // do stuff... 
    }; 
} 

... E qual è la differenza tra i due comunque? Cosa dovrei considerare?

+0

'@ synchronized' è molto lento. Non riesco a trovare le metriche che sto cercando in questo momento, ma anche controllare https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html. – Richard

+0

Se i dati arrivano tramite la stessa coda di invio (stesso thread), non si scontreranno. Se userete code diverse (thread differenti), allora sarebbe necessaria una sincronizzazione. – Jeremy

+0

Trovato (via http://stackoverflow.com/q/10094361/480850): http://perpendiculo.us/?p=133 – Richard

risposta

5

Anche se la differenza funzionale potrebbe non importa molto a voi, è quello che ci si aspetta: se si @synchronize poi il filo si è in è bloccato fino a quando si può ottenere l'esecuzione esclusiva. Se si invia a una coda di invio seriale in modo asincrono, il thread chiamante può andare avanti con altre cose e qualsiasi cosa stia facendo si verificherà sempre sulla stessa coda nota.

quindi sono equivalenti per garantire che una terza risorsa è utilizzata da una sola coda alla volta.

Dispacciamento potrebbe essere un'idea migliore se, per esempio, si ha una risorsa a cui si accede dall'interfaccia utente dalla coda principale e si voleva mutare esso. Quindi il codice dell'interfaccia utente non ha bisogno esplicitamente di @synchronize, nascondendo la complessità del proprio schema di thread all'interno dell'oggetto in modo abbastanza naturale. Anche il dispacciamento sarà un'idea migliore se hai un attore centrale che può innescare molti di questi cambiamenti su altri attori diversi; questo permetterà loro di operare contemporaneamente.

sincronizzazione è più compatta e molto più facile fare un passo di debug. Se quello che stai facendo tende a essere di due o tre righe e dovresti comunque distribuirlo in modo sincrono, allora non vale la pena di dedicarsi allo sforzo di creare una coda, specialmente considerando i costi impliciti della creazione un blocco e spostandolo sul mucchio.

+0

Grazie per la risposta dettagliata.Sembra che la coda asincrona sia ciò che volevo dopo tutto. – livingtech

4

Nel secondo caso si potrebbe bloccare il thread chiamante fino a quando "fare le cose" è stato fatto. Usando le code e dispatch_async non bloccherai il thread chiamante. Ciò sarebbe particolarmente importante se si chiama sortArrayIntoLocalStore dal thread dell'interfaccia utente.