Какова точная причина для использования 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;
}
Разве это не плохая идея, чтобы создать экземпляр Singleton асинхронно в фоновом режиме? Я имею в виду, что произойдет, если я запрашиваю этот общий экземпляр и сразу полагаюсь на него, но dispatch_once занимает до Рождества, чтобы создать мой объект? Не сразу возвращается, верно? По крайней мере, в этом и заключается весь смысл Grand Central Dispatch.
Так почему они это делают?
ios
objective-c
singleton
automatic-ref-counting
Гордый член
источник
источник
Note: static and global variables default to zero.
Ответы:
dispatch_once()
абсолютно синхронно. Не все методы GCD делают вещи асинхронно (в данном случаеdispatch_sync()
это синхронно). Использованиеdispatch_once()
заменяет следующую идиому:Преимущество
dispatch_once()
этого в том, что это быстрее. Это также семантически чище, потому что оно также защищает вас от нескольких потоков, выполняющих alloc init вашего sharedInstance - если они все пытаются в одно и то же время. Это не позволит создать два экземпляра. Вся идеяdispatch_once()
«выполнить что-то один раз и только один раз», и это именно то, что мы делаем.источник
dispatch_once()
это действительно просто (особенно потому, что Xcode даже автоматически заполняет его до полного фрагмента кода для вас) и означает, что вам даже не нужно думать, должен ли метод быть потокобезопасным.+initialize
происходит до того, как к классу прикасаются, даже если вы еще не пытаетесь создать свой общий экземпляр. В общем, ленивая инициализация (создание чего-либо только при необходимости) лучше. Во-вторых, даже ваше заявление о производительности не соответствует действительности.dispatch_once()
занимает почти точно такое же количество времени , как говорятif (self == [MyClass class])
в+initialize
. Если у вас уже есть+initialize
, то да, создание общего экземпляра происходит быстрее, но большинство классов этого не делают.Потому что он будет работать только один раз. Так что если вы попытаетесь получить к нему доступ дважды из разных потоков, это не вызовет проблем.
Майк Эш имеет полное описание в своем блоге « Уход и кормление синглетонов» .
Не все блоки GCD запускаются асинхронно.
источник