ios - variable - swift static shared




Pourquoi Apple recommande-t-il d'utiliser dispatch_once pour implémenter le pattern singleton sous ARC? (2)

Quelle est la raison exacte de l'utilisation de dispatch_once dans l'accesseur d'instance partagée d'un singleton sous 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;
}

N'est-ce pas une mauvaise idée d'instancier le singleton de manière asynchrone en arrière-plan? Je veux dire ce qui se passe si je demande cette instance partagée et que je m'en fie immédiatement, mais dispatch_once prend jusqu'à Noël pour créer mon objet? Il ne revient pas immédiatement non? Au moins, cela semble être tout l'intérêt de Grand Central Dispatch.

Alors pourquoi font-ils cela?


Parce que cela ne fonctionnera qu'une fois. Donc, si vous essayez d'y accéder deux fois à partir de différents threads, cela ne causera pas de problème.

Mike Ash a une description complète dans son article de blog Care and Feeding of Singletons .

Tous les blocs GCD ne sont pas exécutés de manière asynchrone.


dispatch_once() est absolument synchrone. Toutes les méthodes GCD ne font pas les choses de manière asynchrone (cas particulier, dispatch_sync() est synchrone). L'utilisation de dispatch_once() remplace l'idiome suivant:

+ (MyClass *)sharedInstance {
    static MyClass *sharedInstance;
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[MyClass alloc] init];
        }
    }
    return sharedInstance;
}

L'avantage de dispatch_once() est que c'est plus rapide. Il est également plus propre du point de vue sémantique, car il vous protège également contre plusieurs threads faisant l'alloc initial de votre SharedInstance - s'ils essayent tous au même moment. Cela ne permettra pas la création de deux instances. L'idée de dispatch_once() est de "faire quelque chose une fois et une seule fois", ce qui est précisément ce que nous faisons.





automatic-ref-counting