2010-11-02 14 views
5

Was entspricht dem in Ziel c synchronisierten Java? Ich möchte meine Singleton-Methode sicher in der Lage sein zu machen, so dass, wenn es bein von 2 verschiedenen Threads aufgerufen, versuchen sie es zu benutzen 1 von 1.Was ist das Äquivalent von synchronisiert in Objective-C?

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

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

+1

Nicht gerade ein Duplikat, eine ähnliche Frage zu verwenden, sicher. –

Antwort

10

Obj-C ein synchronisiertes Konstrukt hat

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

Rückkehr aus einem synchronisierten Block funktioniert die ‚richtige‘ Sache

+0

Nur ein kleiner Fix, ich denke, die OP will statische Methode verwenden – onmyway133

9

Joshua Antwort ist richtig, aber erfordert, dass Sie ein Objekt haben, auf das synchronisieren. Dies für einen Singleton zu tun, kann zu allen möglichen seltsamen Rennbedingungen führen, wenn Sie nicht vorsichtig sind. Das Standardmuster für einen Singleton ist es in +initialize zu initialisieren, mit dispatch_once, die das Richtige tut:

static MyObject *singleton = nil; 

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

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

Synchronisieren Sie auf der Singleton-Klasse, dann keine ungeraden Rennbedingungen. – JeremyP

+1

Dies ist empfohlene Stil von Apple. – Eonil

-1

ich mit beiden Antworten zustimmen. Aber wenn die Idee auf Nachfrage instanziiert ist, dann würde ich mit Joshua Vorschlag geht mit einer leichten Modifikation mit doppelt geprüft hemmend:

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

Auf diese Weise kann unnötige Verriegelung zu vermeiden, nachdem das Objekt instanziiert wurde.

+2

Es gibt viele subtile mögliche Wettlaufbedingungen mit doppelt überprüfter Verriegelung. Ich würde es vermeiden. – JeremyP

+0

Das war nicht meine Stimme unten btw – JeremyP

+0

Ich schätze Ihr Feedback JeremyP, ich gebe zu, dass ich solche Probleme nicht bewusst war. Aber ich denke immer noch, dass es sich lohnt, diese Probleme zu verstehen und es richtig zu machen, vor allem, wenn dieser Code stark frequentiert wird, wäre es schade, wissentlich einen möglichen Streitpunkt hinzuzufügen. Sehr geschätzt! – fhj

8

Zum Synchronisieren der Singleton-Erstellung sollten Sie die Singleton-Klasse als zu synchronisierendes Objekt verwenden. Dies ist meine übliche Muster:

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

Punkte zu beachten:

  • Ich habe es sich um eine Klasse-Methode. Sie müssen das nicht, es wird als Instanzmethode funktionieren.

  • Normalerweise innerhalb von Klassenmethoden, wenn Sie auf die Klasse verweisen, würden Sie self (oder [self class] in Instanzmethoden) verwenden. Dies wäre jedoch hier falsch, da Unterklassen mit einem anderen Objekt als die MyObject-Klasse synchronisiert würden.

  • Ich habe die Rückkehr außerhalb der @synchronize Block. Es ist vollkommen in Ordnung, von innerhalb des Blocks zurückzukehren, aber wenn Sie dies tun, erhalten Sie eine unechte Warnung, dass die Methode möglicherweise keinen Wert zurückgibt.


bearbeiten

Das obige Muster ist längst überholt. Am besten ist es die dispatch_once

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

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

statisches MyObject * singleton = null; Setzt dies nicht das Singleton-Objekt auf Null und instantiiert es jedes Mal, wenn die Methode aufgerufen wird? – aryaxt

+0

IIRC, in ObjC, bedeutet statisch im Grunde genommen "nur eine davon existiert" folglich wird es nur einmal initialisiert. – JimR

+3

Statisch in Obj-C ist das gleiche wie in C, was bedeutet, dass Zeile nur einmal initialisiert wird –

Verwandte Themen