2010-11-02 20 views
5

¿Cuál es el equivalente de java sincronizado en el objetivo c? Quiero ser capaz de hacer que mi método de Singleton segura, por lo que cuando es bein llamada de 2 hilos diferentes, tratan de usarlo 1 por 1.¿Cuál es el equivalente de sincronizado en Objective-C?

+(MyObject*) getSharedObject 
{ 
    if(!singleton) 
    { 
      singleton = [[MyObject alloc] init]; 
    } 
    return singleton; 
} 
+0

duplicado http://stackoverflow.com/questions/1215330/how-does-synchronized-lock-unlock-in-objective-c –

+1

No es exactamente un duplicado, una pregunta relacionada con el patrón dispatch_once Por supuesto. –

Respuesta

10

Obj-C tiene un sincronizado construir

-(MyObject*) getSharedObject 
{ 
@synchronized(something) 
{ 
    if(!singleton) 
    { 
      singleton = [[MyObject alloc] init]; 
    } 
    return singleton; 
} 
} 

volver de dentro de un bloque sincronizado hace el 'derecho' cosa

+0

Solo una pequeña corrección, creo que OP quiere usar el método estático – onmyway133

9

respuesta de Joshua es correcta, pero requiere que haya un objeto en el que desea sincronizar. Hacer esto para un singleton puede conducir a todo tipo de condiciones raras de carrera si no tienes cuidado. El patrón estándar para un conjunto unitario es inicializar en +initialize, utilizando dispatch_once, que hace lo correcto:

static MyObject *singleton = nil; 

+ (void)initialize { 
    static dispatch_once_t pred; 
    dispatch_once(&pred, ^{ singleton = [[MyObject alloc] init]; }); 
} 

- (MyObject&)getSharedObject 
{ 
    return singleton; 
} 
+2

Sincronice en la clase de singleton, entonces no hay condiciones de carrera extrañas. – JeremyP

+1

Este es el estilo recomendado por Apple. – Eonil

-1

Estoy de acuerdo con las dos respuestas. Pero si la idea es crear una instancia de la demanda entonces me gustaría ir con la sugerencia de Joshua con una ligera modificación usando-doble comprobación de bloqueo:

if (!singleton) 
    @synchronized(something) 
     if (!singleton) 
     instantiate; 

esta manera evitar el bloqueo innecesario después de que el objeto ha creado una instancia.

+2

Hay muchas condiciones sutiles de carrera posibles involucradas con el doble bloqueo comprobado. Lo evitaría. – JeremyP

+0

Ese no fue mi voto negativo por cierto – JeremyP

+0

Agradezco sus comentarios JeremyP, admito que no estaba al tanto de tales problemas. Sin embargo, todavía creo que vale la pena el esfuerzo para comprender esos problemas y hacerlo bien, especialmente si este código va a ser de alto tráfico, será una lástima agregar a sabiendas un posible punto de contención. ¡Muy apreciado! – fhj

8

Para sincronizar la creación de singleton, debe usar la clase singleton como el objeto para sincronizar. Este es mi patrón habitual:

+(MyObject*) singleton 
{ 
    static MyObject* singleton = nil; 
    @synchronized([MyObject class]) 
    { 
     if(singleton == nil) 
     { 
      singleton = [[MyObject alloc] init]; 
     } 
    } 
    return singleton; 
} 

Puntos a tener en cuenta:

  • He dejado un método de clase. En realidad no tienes que hacerlo, funcionará como un método de instancia.

  • Normalmente, en los métodos de clase cuando se hace referencia a la clase, debe usar self (o [self class] en métodos de instancia). Sin embargo, eso sería incorrecto porque las subclases se sincronizarían usando un objeto diferente a la clase MyObject.

  • He puesto la devolución fuera del bloque @synchronize. Está perfectamente bien regresar desde el interior del bloque, pero si lo haces, recibes una advertencia falsa del analizador estático clang diciendo que el método podría no devolver un valor.


Editar

El patrón anterior es obsoleto desde hace mucho tiempo. Lo mejor es usar

+(MyObject*) singleton 
{ 
    static dispatch_once_t onceToken; 
    static MyObject* singleton = nil; 

    dispatch_once (&onceToken, ^{ 
     singleton = [[MyObject alloc] init]; 
    }); 
    return singleton; 
} 
+2

static MyObject * singleton = nil; ¿Esto no establece el objeto singleton en cero y vuelve a crear instancias cada vez que se llama al método? – aryaxt

+0

IIRC, en ObjC, static significa básicamente "solo uno de estos existe" en consecuencia, solo se inicializa una vez. – JimR

+3

Estático en Obj-C es lo mismo que en C, lo que significa que la línea solo se inicializará una vez –

Cuestiones relacionadas