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

在后台asynchronous实例化单例不是一个坏主意吗? 我的意思是,如果我请求共享实例并立即依赖它,会发生什么情况,但dispatch_once需要等到圣诞节才创build我的对象? 它不立即返回正确的? 至less这似乎是大中央调度的重点。

那他们为什么要这样做?

dispatch_once()是绝对同步的。 并非所有GCD方法都是asynchronous执行的(例如, dispatch_sync()是同步的)。 dispatch_once()的使用取代了下面的习惯用法:

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

dispatch_once()在这方面的好处是速度更快。 它在语义上也是更清洁的,因为它也保护你免受多个线程的影响,执行你的sharedInstance的alloc init – 如果他们都试着在同一时间。 它不会允许创build两个实例。 dispatch_once()的整个想法是“只执行一次,只执行一次”,这正是我们正在做的事情。

因为它只会运行一次。 所以如果你尝试从不同的线程访问它两次,它不会造成问题。

Mike Ash在他关心和喂食单身的博客文章中有完整的描述。

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