为什么苹果推荐使用dispatch_once来实现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;
}

在后台异步实例化单例是不是一个坏主意?我的意思是,如果我请求共享实例并立即依赖它,但dispatch_once直到圣诞节才创建对象,会发生什么?它不会立即返回,对吧?至少这似乎是中央调度的全部意义所在。

他们为什么要这么做呢?

79142 次浏览

因为它只会运行一次。因此,如果您尝试从不同的线程访问它两次,它不会引起问题。

Mike Ash在他的照顾和喂养独生子女博客文章中有完整的描述。

并非所有GCD块都是异步运行的。

dispatch_once()是绝对同步的。并不是所有的GCD方法都是异步的(例如,dispatch_sync()是同步的)。dispatch_once()的使用替换了以下习语:

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

dispatch_once()相对于this的好处是它更快。它在语义上也更干净,因为它还可以防止多个线程对你的sharedInstance进行alloc init——如果它们都在同一时间尝试的话。它不允许创建两个实例。dispatch_once()的整个思想是“执行某件事一次且仅一次”,这正是我们正在做的。