ios - bloques sincronizados y dispatch_async
objective-c ios6 (2)
¿Qué sucede con el bloqueo en IOS utilizando @synchronized () cuando llamamos a dispatch_async () dentro del bloque?
Por ejemplo:
id myID
-(void) foobar
{
@synchronized(myID){
dispatch_async(){ //do stuff with myID};
}
}
¿El bloqueo sigue siendo válido dentro de la llamada dispatch_async? O, lo que es más importante, ¿tiene algún inconveniente el uso de otra llamada @synchronized () dentro de dispatch_async ()?
El bloqueo allí solo evitaría que se envíen dos bloques diferentes a la vez. Sin embargo, se envían de forma asíncrona, por lo que pueden realizarse o pueden realizarse arbitrariamente en el futuro. La llamada de despacho tampoco esperará a que se completen.
Entonces, las cosas dentro del bloque no están sincronizadas. Las opciones para lograr eso con cambios mínimos son un envío síncrono o simplemente @synchronizing dentro del bloque.
Dependiendo de lo que esté haciendo, la mejor idea podría ser establecer una cola de envío en serie y enviar sus bloques a eso.
Suponiendo que está tratando de sincronizar la interacción con este objeto myID
en la cola de fondo, quiere que al revés, el bloqueo dentro del bloque enviado. En este momento tienes:
@synchronized(myID) {
dispatch_async(queue, ^{
// do stuff with myID
});
}
Eso es sincronizar el proceso de agregar el bloque enviado a su cola, pero no sincroniza lo que está haciendo en segundo plano. Sospecho que eso no es lo que querías decir.
Probablemente tenías la intención de:
dispatch_async(queue, ^{
@synchronized(myID) {
// do stuff with myID
}
});
Se ve muy similar, pero da como resultado un comportamiento completamente diferente. Ahora, el trabajo enviado a la cola de fondo se sincroniza.
Como un refinamiento adicional, si este bloque enviado es posiblemente lento (y supongo que puede ser), entonces probablemente quiera restringir el bloque @synchronized
tanto como sea posible:
dispatch_async(queue, ^{
// do slow stuff in preparation for interacting with `myID`
@synchronized(myID) {
// quickly do stuff with myID
}
// do anything else here
});
Si haces todo el bloque de fondo dentro de un bloque @synchronized
, puedes vencer el propósito completo de enviarlo a un segundo plano, a saber, para minimizar el impacto en la cola principal. Esta última versión mitiga ese problema.
Como observación final, si tiene una cola en serie (o una cola concurrente no global en la que realiza actualizaciones con una barrera), a menudo se utiliza como una técnica que elimina la necesidad de bloqueos por completo, siempre y cuando todas las actualizaciones y consultas para myID
se envían a esa cola. Consulte Eliminación del código basado en bloqueo en la Guía de programación de simultaneidad.