¿@Synchronized no utiliza "bloquear" y "desbloquear" para lograr la exclusión mutua? ¿Cómo se bloquea / desbloquea entonces?
La salida del siguiente programa es solo "Hello World".
@interface MyLock: NSLock<NSLocking>
@end
@implementation MyLock
- (id)init {
return [super init];
}
- (void)lock {
NSLog(@"before lock");
[super lock];
NSLog(@"after lock");
}
- (void)unlock {
NSLog(@"before unlock");
[super unlock];
NSLog(@"after unlock");
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MyLock *lock = [[MyLock new] autorelease];
@synchronized(lock) {
NSLog(@"Hello World");
}
[pool drain];
}
objective-c
synchronization
David Lin
fuente
fuente
lock
objeto se crea en cada llamada, por lo que nunca habrá un caso en el que un@synchronized
bloque bloquee a otro. Y esto significa que no hay exclusión mutua.) Por supuesto, el ejemplo anterior está haciendo la operaciónmain
, por lo que no hay nada que excluir de todos modos, pero uno no debe copiar ciegamente ese código en otro lugar.Respuestas:
La sincronización de nivel de lenguaje Objective-C usa el mutex, al igual que
NSLock
hace. Semánticamente hay algunas pequeñas diferencias técnicas, pero es básicamente correcto pensar en ellas como dos interfaces separadas implementadas sobre una entidad común (más primitiva).En particular con un
NSLock
tiene un bloqueo explícito mientras que con@synchronized
que con un bloqueo implícito asociado con el objeto que está utilizando para sincronizar. El beneficio del bloqueo de nivel de lenguaje es que el compilador lo comprende para que pueda lidiar con problemas de alcance, pero mecánicamente se comportan básicamente igual.Puedes pensar
@synchronized
como una reescritura del compilador:se transforma en:
Eso no es exactamente correcto porque la transformación real es más compleja y usa bloqueos recursivos, pero debería transmitir el punto.
fuente
En Objective-C, un
@synchronized
bloque maneja el bloqueo y desbloqueo (así como las posibles excepciones) automáticamente para usted. El tiempo de ejecución genera dinámicamente un NSRecursiveLock asociado con el objeto con el que está sincronizando. Esta documentación de Apple lo explica con más detalle. Es por eso que no está viendo los mensajes de registro de su subclase NSLock: el objeto en el que sincroniza puede ser cualquier cosa, no solo un NSLock.Básicamente,
@synchronized (...)
es una construcción conveniente que simplifica su código. Al igual que la mayoría de las abstracciones simplificadoras, tiene gastos generales asociados (piense en ello como un costo oculto), y es bueno ser consciente de eso, pero el rendimiento bruto probablemente no sea el objetivo supremo cuando se usan tales construcciones de todos modos.fuente
Realmente
se transforma directamente en:
Esta API disponible desde iOS 2.0 e importada usando ...
fuente
@synchronized
bloque agrega implícitamente un controlador de excepción al código protegido. Este controlador libera automáticamente el mutex en caso de que se produzca una excepción".La implementación de Apple de @synchronized es de código abierto y se puede encontrar aquí . Mike ash escribió dos publicaciones realmente interesantes sobre este tema:
En pocas palabras, tiene una tabla que asigna punteros de objetos (usando sus direcciones de memoria como claves) a
pthread_mutex_t
bloqueos, que se bloquean y desbloquean según sea necesario.fuente
Simplemente asocia un semáforo con cada objeto, y lo usa.
fuente