Почему компания Apple рекомендует использовать один раз направить для реализации шаблона Singleton под дуги?


какова точная причина использования dispatch_once в методе доступа к общему экземпляру синглтона под дугой?

+ (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;
}

разве это не плохая идея, чтобы создать одноэлементный асинхронно в фоновом режиме? Я имею в виду, что произойдет, если я запрошу этот общий экземпляр и сразу же положусь на него, но dispatch_once займет до Рождества, чтобы создать мой объект? Он не возвращается сразу же правильно? По крайней мере, в этом, по-видимому, и заключается весь смысл Grand Central Dispatch.

Так зачем они это делают?

2 297

2 ответа:

dispatch_once() абсолютно синхронно. Не все методы GCD делают вещи асинхронно (например,dispatch_sync() синхронно). Использование dispatch_once() заменяет следующую идиому:

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

пользу dispatch_once() над этим, что это быстрее. Это также семантически чище, потому что он также защищает вас от нескольких потоков, выполняющих alloc init вашего sharedInstance-если они все пытаются в одно и то же время. Это не позволит создать два экземпляра. Вся идея dispatch_once() это "выполнить что-то один раз и только один раз", что именно то, что мы делаем.

потому что он будет работать только один раз. Поэтому, если вы попытаетесь получить к нему доступ дважды из разных потоков, это не вызовет проблем.

Майк Эш имеет полное описание в его уход и кормление Синглетов сообщение в блоге.

не все блоки GCD выполняются асинхронно.