我有一个并发类型为 NSMainQueueConcurrencyType 的 managedObjectContext
+ (NSManagedObjectContext *)managedObjectContextMainThread
{
static NSManagedObjectContext *__managedObjectContext=nil;
@synchronized(self)
{
if (__managedObjectContext != nil)
{
}
else {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
}
}
return __managedObjectContext;
}
除非设置另一个 managedObjectContext.parent,否则永远不会在主线程之外访问主 managedObjectContext。因此 mainManagedObjectContext 是所有线程的父级。
现在当我运行程序时,有时它会陷入僵局。我暂停了程序,这就是我所看到的:
正如我们在图片中看到的,有 2 个线程似乎处于死锁状态。第一个是主线程。
它在@synchronize (self) 上死锁。合理的。
另一个线程死锁:
因此,当尝试更改保存 __managedObjectContext 的静态变量的持久存储时,它会锁定。
让我把代码再次重申一遍:
+ (NSManagedObjectContext *)managedObjectContextMainThread
{
static NSManagedObjectContext *__managedObjectContext=nil;
@synchronized(self) //Main thread deadlock here
{
if (__managedObjectContext != nil)
{
}
else {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[__managedObjectContext setPersistentStoreCoordinator:coordinator]; //Secondary thread dead lock here
}
}
}
return __managedObjectContext;
}
我的问题是为什么在地球上[__managedObjectContext setPersistentStoreCoordinator:coordinator];
没有其他东西正在访问 __managedObjectContext。第二个线程(非主线程)试图将 __managedObjectContext 设置为父上下文。第一个线程只是在@synchronized 中愉快地等待。它什么也没做。
那么为什么会出现死锁以及如何解决呢?
哦,子 managedObjectContext 是在这里创建的:
@synchronized(self)
{
if ([managedObjectContexts objectForKey:[self threadKey]] == nil ) {
NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
threadContext.parentContext = [self managedObjectContextMainThread]; //Stuck here. This goes straight to above function managedObjectContextMainThread where it stucks.
threadContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
[managedObjectContexts setObject:threadContext forKey:[self threadKey]];
}
}