ios 为什么Apple推荐使用dispatch_once来实现ARC下的单例模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9119042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does Apple recommend to use dispatch_once for implementing the singleton pattern under ARC?
提问by Proud Member
What's the exact reason for using dispatch_once in the shared instance accessor of a singleton under ARC?
在 ARC 下单例的共享实例访问器中使用 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;
}
Isn't it a bad idea to instantiate the singleton asynchronously in the background? I mean what happens if I request that shared instance and rely on it immediately, but dispatch_once takes until Christmas to create my object? It doesn't return immediately right? At least that seems to be the whole point of Grand Central Dispatch.
在后台异步实例化单例不是一个坏主意吗?我的意思是,如果我请求该共享实例并立即依赖它,但 dispatch_once 需要到圣诞节才能创建我的对象,会发生什么?它不会立即返回对吗?至少这似乎是 Grand Central Dispatch 的重点。
So why are they doing this?
那么他们为什么要这样做呢?
回答by Lily Ballard
dispatch_once()
is absolutely synchronous. Not all GCD methods do things asynchronously (case in point, dispatch_sync()
is synchronous). The use of dispatch_once()
replaces the following idiom:
dispatch_once()
是绝对同步的。并非所有 GCD 方法都是异步执行的(例如,dispatch_sync()
是同步的)。的使用dispatch_once()
取代了以下习语:
+ (MyClass *)sharedInstance {
static MyClass *sharedInstance;
@synchronized(self) {
if (sharedInstance == nil) {
sharedInstance = [[MyClass alloc] init];
}
}
return sharedInstance;
}
The benefit of dispatch_once()
over this is that it's faster. It's also semantically cleaner, because it also protects you from multiple threads doing alloc init of your sharedInstance--if they all try at the same exact time. It won't allow two instances to be created. The entire idea of dispatch_once()
is "perform something once and only once", which is precisely what we're doing.
这样做的好处dispatch_once()
是它更快。它在语义上也更清晰,因为它还可以保护您免受多个线程执行 sharedInstance 的 alloc init 的影响——如果它们都在同一时间尝试。它不允许创建两个实例。整个想法dispatch_once()
是“执行一次且仅一次”,这正是我们正在做的。
回答by Abizern
Because it will only run once. So if you try and access it twice from different threads it won't cause a problem.
因为它只会运行一次。因此,如果您尝试从不同的线程访问它两次,它不会导致问题。
Mike Ash has a full description in his Care and Feeding of Singletonsblog post.
Mike Ash 在他对单身人士的关心和喂养博客文章中有完整的描述。
Not all GCD blocks are run asynchronously.
并非所有 GCD 块都是异步运行的。