从主队列调用dispatch_sync时,iOS死锁,执行的块保存到Core数据

时间:2014-03-09 14:38:16

标签: ios ipad core-data deadlock

我有一个使用父上下文的Core Data实现。 我有一个在主队列上运行的主上下文和在私有队列上运行的后台上下文,主上下文是他的父。

我使用以下内容覆盖了上下文保存方法:

- (BOOL)save:(NSError **)error {
  BOOL retVal = YES;

  if (self.parentContext) {
    //push changes to parent context.
    retVal = [super save:error];

    if (retVal) {
      //save parent context.
      [self.parentContext performBlock:^{
        [self.parentContext save:error];
      }];
    }
  } else {
    //save changes.
    retVal = [super save:error];
  }

  return retVal;
}

我的问题是我的主队列调用时:

- (BOOL)doSomething {
  __block BOOL retVal;

  dispatch_sync(workerQueue, ^{
    retVal = [super doSomething];
  });

  return retVal;
}

如果[super doSomething]调用了上下文保存方法,我会遇到死锁(死锁是在我的保存方法中的行retVal = [super save:error];)。

以下是工作队列的堆栈跟踪:

0 semaphore_wait_trap
1_dispatch_thread_semaphore_wait$VARIANT$mp
2_dispatch_barrier_sync_f_slow
3_perform 
4-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error]
5 -[NSManagedObjectContext save:]

以下是主队列的堆栈跟踪:

0 semaphore_wait_trap 
1 _dispatch_thread_semaphore_wait$VARIANT$mp 
2 _dispatch_barrier_sync_f_slow 
3 [Service doSomething]

由于一些奇怪的原因,这种情况只发生在iPad而不是iPhone上

有没有办法使用递归锁来克服这个死锁?

1 个答案:

答案 0 :(得分:2)

您不得将自己的调度队列用于核心数据操作。使用performBlock:performBlockAndWait:以确保在队列上执行操作 与托管对象上下文相关联。

请参阅NSManagedObjectContext Class Reference中的“并发”。