看 rect native 的 commit,发现个好玩的地方,看下面代码有问题吗?
+ (instancetype)defaultStack {
static KACoreDataStack *stack;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if ([NSThread isMainThread]) {
stack = [[KACoreDataStack alloc] init];
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
stack = [[KACoreDataStack alloc] init];
});
}
});
return stack;
}
这个会导致死锁,当后台线程在执行dispatch_sync 前,主线程执行到dispatch_once,会导致死锁。详细可以看这篇文章Initializing on the main thread using dispatch_once without race conditions
解决方案
void dispatch_once_on_main_thread(dispatch_once_t *predicate,
dispatch_block_t block) {
if ([NSThread isMainThread]) {
dispatch_once(predicate, block);
} else {
if (DISPATCH_EXPECT(*predicate == 0L, NO)) {
dispatch_sync(dispatch_get_main_queue(), ^{
dispatch_once(predicate, block);
});
}
}
}