2013-09-04 10 views
10

Cosa succede al blocco in IOS utilizzando @synchronized() quando chiamiamo dispatch_async() all'interno del blocco.blocchi sincronizzati e dispatch_async

Per esempio:

id myID 
-(void) foobar 
{ 
    @synchronized(myID){ 
     dispatch_async(){ //do stuff with myID}; 
    } 
} 

è la serratura ancora valida all'interno della chiamata dispatch_async? O ancora più importante c'è qualche inconveniente nell'usare un'altra chiamata @synchronized() all'interno di dispatch_async()?

+0

Cosa stai cercando di ottenere? – Wain

+0

BTW, ho ragione a ritenere che tu non sia _non_ reinstantiating 'myID' in nessun punto? Il blocco '@ synchronized' è unico per quella particolare istanza dell'oggetto puntata da' myID', non dalla variabile in generale. – Rob

risposta

3

Il blocco eviterebbe solo l'invio di due blocchi diversi contemporaneamente. Tuttavia vengono inviati in modo asincrono, quindi possono essere eseguiti in quel momento o possono essere eseguiti arbitrariamente in un lontano futuro. Anche la chiamata di spedizione non aspetterà che si completino.

Quindi la roba all'interno del blocco non è sincronizzata. Le opzioni per raggiungere questo obiettivo con modifiche minime sono una distribuzione sincrona o solo @ sincronizzazione con il blocco.

A seconda di cosa si sta facendo, l'idea migliore potrebbe essere quella di stabilire una coda di invio seriale e inviare i blocchi su quello.

8

Supponendo che si stia tentando di sincronizzare l'interazione con questo oggetto myID nella coda di sfondo, si desidera il contrario, il blocco all'interno del blocco inviato. In questo momento si dispone di:

@synchronized(myID) { 
    dispatch_async(queue, ^{ 
     // do stuff with myID 
    }); 
} 

Ecco sincronizzare il processo di aggiunta del blocco inviato alla coda, ma lo fa non sincronizzare quello che stai facendo in background. Sospetto che non sia quello che intendevi.

Probabilmente destinato:

dispatch_async(queue, ^{ 
    @synchronized(myID) { 
     // do stuff with myID 
    } 
}); 

Sembra molto simile, ma i risultati in un comportamento completamente diverso. Ora, il lavoro inviato alla coda in background è in fase di sincronizzazione.

Come ulteriore affinamento, se questo inviato blocco è forse lento (e presumo che sia), allora si sarebbe probabilmente per vincolare la @synchronized blocco il più possibile:

dispatch_async(queue, ^{ 

    // do slow stuff in preparation for interacting with `myID` 

    @synchronized(myID) { 
     // quickly do stuff with myID 
    } 

    // do anything else here 
}); 

Se eseguire tutto il blocco in background all'interno di un blocco @synchronized, è possibile annullare l'intero scopo di inviarlo allo sfondo, ovvero minimizzare l'impatto sulla coda principale. Quest'ultima interpretazione mitiga quel problema.

Come osservazione finale, se si dispone di una coda seriale (o di una coda concorrente non globale in cui si esegue l'aggiornamento con una barriera), viene spesso utilizzata come tecnica che elimina del tutto la necessità di serrature, a patto che tutti gli aggiornamenti e le richieste per myID vengono inviati a quella coda. Vedere Eliminating Lock-Based Code nella Guida alla programmazione simultanea .

+0

Quando dici "minimizzare l'impatto sulla coda principale" intendi solo che il processo in background richiederà più tempo, giusto? Il lavoro è ancora in corso nella coda di sfondo e, ad es. bloccare l'interfaccia utente. – Ixx

+0

@Ixx - No, il mio punto è che se (a) si fa qualcosa in termini di tempo all'interno di un blocco '@ sincronizzato' su un thread in background; e (b) se il thread principale ha anche bisogno di accedere a 'myID' (e quindi dovrebbe usare' @ synchronized', anche), il tuo background '@ synchronized' block può facilmente bloccare il thread principale, vanificando lo scopo di inviare questo roba su una coda di sfondo del tutto. Quindi, quando il thread in background deve fare '@ synchronized', assicurati di entrare e uscire il più rapidamente possibile, mantenendo le cose che richiedono molto tempo al di fuori del blocco' @ synchronized', se puoi. – Rob