203 votos

¿@synchronized bloqueo/desbloqueo en Objective-C?

Hace @synchronized no utilice "lock" y "abrir" para lograr la exclusión mutua. ¿Cómo bloquear/desbloquear entonces?

La salida del siguiente programa es sólo "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];
}

328voto

Louis Gerbarg Puntos 33025

El lenguaje Objective-C nivel de sincronización utiliza la exclusión mutua, como NSLock . Semánticamente, hay algunas pequeñas diferencias técnicas, pero es básicamente correcto al pensar en ellos como dos separar interfaces implementadas en la parte superior de una común (más primitivos) de la entidad.

En particular, con un NSLock tiene un explícito de bloqueo, mientras que con @synchronized tiene implícito un bloqueo asociado con el objeto que se utiliza para sincronizar. La ventaja del idioma, el nivel de cierre es el compilador entiende que para que pueda lidiar con el alcance de las cuestiones, pero mecánicamente se comportan básicamente el mismo.

Usted puede pensar en @synchronized como un compilador de reescritura:

- (NSString *)myString {
  @synchronized(self) {
    return [[myString retain] autorelease];
  }
}

se transforma en:

- (NSString *)myString {
  NSString *retval = nil;
  pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
  pthread_mutex_lock(self_mutex);
  retval = [[myString retain] autorelease];
  pthread_mutex_unlock(self_mutex);
  return retval;
}

Que no es exactamente correcto, porque la real transformación es más compleja y utiliza recursiva bloqueos, pero se debe conseguir el punto a través.

42voto

Quinn Taylor Puntos 29688

En Objective-C, @synchronized bloque controla el bloqueo y desbloqueo (así como las posibles excepciones) automáticamente para usted. El tiempo de ejecución de forma dinámica, esencialmente, genera un NSRecursiveLock que está asociada con el objeto que se está sincronizando. Esta documentación de Apple se explica en más detalle. Esta es la razón por la que no estamos viendo los mensajes de registro de su NSLock subclase - el objeto de sincronizar, puede ser cualquier cosa, no sólo un NSLock.

Básicamente, @synchronized (...) es una conveniencia de construir que simplifica el código. Como la mayoría de la simplificación de las abstracciones, se ha asociado la cabeza (pensar en él como un costo oculto), y es bueno ser consciente de eso, pero el rendimiento bruto es, probablemente, no la meta suprema, cuando el uso de tales construcciones de todos modos.

31voto

Dirk Theisen Puntos 101

En realidad

{
  @synchronized(self) {
    return [[myString retain] autorelease];
  }
}

transforma directamente en:

// needs #import <objc/objc-sync.h>
{
  objc_sync_enter(self)
    id retVal = [[myString retain] autorelease];
  objc_sync_exit(self);
  return retVal;
}

Esta API disponible desde iOS 2.0 e importada usando...

#import <objc/objc-sync.h>

-4voto

Pavel Minaev Puntos 60647

Solo un semáforo se asocia con cada objeto y lo usa.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X