带有NSPrivateQueueConcurrencyType的existingObjectWithID死锁

时间:2014-01-13 04:32:05

标签: objective-c multithreading core-data deadlock afincrementalstore

我正在使用NSPrivateQueueConcurrencyType并发类型而不是NSMainQueueConcurrencyType进行冻结(死锁?)。

我的上下文初始化:

_managedObjectContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSPrivateQueueConcurrencyType];  
[_managedObjectContext setPersistentStoreCoordinator:coordinator];

麻烦的代码:

NSManagedObjectID *managedObjectID = [self managedObjectIDForEntity:entity 
withParseObjectId:object.objectId];  
managedObject = [context existingObjectWithID:managedObjectID error:error];

回溯: backtrace

链接到Github projectopen issue以了解该问题的某些背景信息。

1 个答案:

答案 0 :(得分:4)

你已经开枪了。

executeFetchRequest:error:创建一个单独的子上下文,它可以在其上执行某些工作(而父队的队列被阻止)。这项工作涉及将工作同步分派到父队列(通过insertOrUpdateObjects:)。

这是因为具有嵌套上下文的NSManagedObjectContext -existingObjectWithId:会调度到父队列,以完成故障到父上下文的对象。很遗憾,您已经在子级上下文中使用performBlockAndWait阻止了父级队列。

随之而来的是悲伤。


编辑:关于可能的解决方案的想法

这里的问题是由使用具有不同队列的嵌套上下文引起的。我不确定在这种情况下我是否理解使用嵌套上下文的动机,除非提供的上下文是NSMainQueueConcurrencyType。

即使这样,强制取消调用上下文队列的工作也是危险的,因为如果它们出现故障(如此处所述),则fetch中的任何现有对象都将成为此问题的牺牲品。

在这种情况下,AFIncrementalStore可能会以某种方式保证图形隔离。我发现这个问题是针对AFNetwork提出的:

https://github.com/AFNetworking/AFIncrementalStore/commit/1f822279e6a7096327ae56a2f65ce8e2ff36da83

可疑的是,保留周期阻止了对象被解除分配,从而导致它永久存在于父上下文中并且死锁试图发生故障。