在 dispatch_once 中执行主线程

看 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);
      });
    }
  }
}

你可能感兴趣的:(在 dispatch_once 中执行主线程)