Was ist der genaue Grund für die Verwendung von dispatch_once im gemeinsam genutzten Instanz-Accessor eines Singletons unter ARC?
+ (MyClass *)sharedInstance
{
// Static local predicate must be initialized to 0
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
sharedInstance = [[MyClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
Ist es nicht eine schlechte Idee, den Singleton asynchron im Hintergrund zu instanziieren? Ich meine, was passiert, wenn ich diese gemeinsam genutzte Instanz anfordere und mich sofort darauf verlasse, aber dispatch_once bis Weihnachten braucht, um mein Objekt zu erstellen? Es kehrt nicht sofort zurück, oder? Zumindest scheint das der springende Punkt bei Grand Central Dispatch zu sein.
Warum machen sie das?
ios
objective-c
singleton
automatic-ref-counting
Stolzes Mitglied
quelle
quelle
Note: static and global variables default to zero.
Antworten:
dispatch_once()
ist absolut synchron. Nicht alle GCD-Methoden führen asynchrone Aktionen aus (Beispiel:dispatch_sync()
Synchron). Die Verwendung vondispatch_once()
ersetzt die folgende Redewendung:Der Vorteil
dispatch_once()
davon ist, dass es schneller ist. Es ist auch semantisch sauberer, da es Sie auch vor mehreren Threads schützt, die die Initiierung Ihrer sharedInstance durchführen - wenn alle es genau zur gleichen Zeit versuchen. Es können keine zwei Instanzen erstellt werden. Die gesamte Idee vondispatch_once()
"etwas einmal und nur einmal ausführen" ist genau das, was wir tun.quelle
dispatch_once()
ist jedoch sehr einfach (insbesondere, weil Xcode es sogar automatisch zu einem vollständigen Code-Snippet für Sie vervollständigt) und bedeutet, dass Sie nicht einmal überlegen müssen, ob die Methode threadsicher sein muss.+initialize
, bevor die Klasse berührt wird, auch wenn Sie noch nicht versuchen, Ihre freigegebene Instanz zu erstellen. Im Allgemeinen ist eine verzögerte Initialisierung (nur bei Bedarf etwas erstellen) besser. Zweitens ist selbst Ihr Leistungsanspruch nicht wahr.dispatch_once()
dauert fast genauso lange wieif (self == [MyClass class])
in+initialize
. Wenn Sie bereits eine haben+initialize
, ist das Erstellen der freigegebenen Instanz dort zwar schneller, die meisten Klassen jedoch nicht.Weil es nur einmal läuft. Wenn Sie also versuchen, zweimal von verschiedenen Threads darauf zuzugreifen, wird dies kein Problem verursachen.
Mike Ash hat eine vollständige Beschreibung in seinem Blog-Beitrag Care and Feeding of Singletons .
Nicht alle GCD-Blöcke werden asynchron ausgeführt.
quelle