在 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);
      });
    }
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • iOS中GCD的使用小结 作者dullgrass 2015.11.20 09:41*字数 4996阅读 20199...
    DanDanC阅读 945评论 0 0
  • 本篇博客共分以下几个模块来介绍GCD的相关内容: 多线程相关概念 多线程编程技术的优缺点比较? GCD中的三种队列...
    有梦想的老伯伯阅读 1,040评论 0 4
  • 目录(GCD): 关键词 混淆点 场景应用 总结 1. 关键词 线程概念: 独立执行的代码段,一个线程同时间只能执...
    Ryan___阅读 1,305评论 0 3
  • 本篇博客共分以下几个模块来介绍GCD的相关内容: 多线程相关概念 多线程编程技术的优缺点比较? GCD中的三种队列...
    dullgrass阅读 37,923评论 30 236
  • 要是能忘记你的名字 也挺好的
    miiika阅读 1,083评论 13 33