带有NSPrivateQueueConcurrencyType的existingObjectWithID死锁

sbo*_*ami 5 multithreading deadlock core-data objective-c afincrementalstore

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

我的上下文初始化

_managedObjectContext = [[NSManagedObjectContext alloc] 
initWithConcurrencyType:NSPrivateQueueConcurrencyType];  
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
Run Code Online (Sandbox Code Playgroud)

麻烦的代码:

NSManagedObjectID *managedObjectID = [self managedObjectIDForEntity:entity 
withParseObjectId:object.objectId];  
managedObject = [context existingObjectWithID:managedObjectID error:error];
Run Code Online (Sandbox Code Playgroud)

回溯: 回溯

链接到Github 项目并针对该问题的某些上下文打开问题.

ImH*_*its 4

你朝自己的脸开枪了。

executeFetchRequest:error:创建一个单独的子上下文,在该子上下文上执行一些工作(当父队列被阻塞时)。这项工作涉及将工作同步分派到父队列(通过insertOrUpdateObjects:)。

这是因为NSManagedObjectContext -existingObjectWithId:嵌套上下文会分派到父级队列,以完成父级上下文中出错的对象。不幸的是,您已经用子上下文阻塞了父performBlockAndWait队列。

随之而来的是巨大的悲伤。


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

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

即使如此,强制从调用上下文的队列中获取数据也是危险的,因为如果出现故障,获取中的任何现有对象都将成为此问题的受害者(正如此处所做的那样)。

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

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

可疑的相似之处在于,保留循环阻止对象被释放,从而导致它永久存在于父上下文中并试图发生死锁。