Почему Apple рекомендует использовать dispatch один раз для реализации одноэлементного шаблона под ARC?
какова точная причина использования dispatch_once в методе доступа к общему экземпляру одноэлементного элемента под 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;
}
разве это не плохая идея создать экземпляр синглтона асинхронно в фоновом режиме? Я имею в виду, что произойдет, если я запрошу этот общий экземпляр и сразу же положусь на него, но dispatch_once займет до Рождества, чтобы создать мой объект? Он не сразу возвращается, верно? По крайней мере, в этом, кажется, весь смысл "Гранд Сентрал Диспетч".
Так зачем они это делают?
2 ответов
dispatch_once()
абсолютно синхронно. Не все методы GCD делают вещи асинхронно (case in point,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 выполняются асинхронно.