【发布时间】:2014-03-29 07:08:45
【问题描述】:
我遇到了无法解决的 Core Data 问题。我已经通过艰难的方式了解了 Core Data 中的并发问题,因此我非常小心,只在 performBlock: 和 performBlockAndWait: 块中执行任何核心数据操作。
这是我的代码:
/// Executes a fetch request with given parameters in context's block.
+ (NSArray *)executeFetchRequestWithEntityName:(NSString *)entityName
predicate:(NSPredicate *)predicate
fetchLimit:(NSUInteger)fetchLimit
sortDescriptor:(NSSortDescriptor *)sortDescriptor
inContext:(NSManagedObjectContext *)context{
NSCAssert(entityName.length > 0,
@"entityName parameter in executeFetchRequestWithEntityName:predicate:fetchLimit:sortDescriptor:inContext:\
is invalid");
__block NSArray * results = nil;
NSPredicate * newPredicate = [CWFCoreDataUtilities currentUserPredicateInContext:context];
if (predicate){
newPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[newPredicate, predicate]];
}
[context performBlockAndWait:^{
NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:entityName];
request.fetchLimit = fetchLimit;
request.predicate = newPredicate;
if (sortDescriptor) {
request.sortDescriptors = @[sortDescriptor];
}
NSError * error = nil;
results = [context executeFetchRequest:request error:&error];
if (error){
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"Fetch requests are required to succeed."
userInfo:@{@"error":error}];
NSLog(@"ERROR! %@", error);
}
NSCAssert(results != nil, @"Fetch requests must succeed");
}];
return results;
}
当我从两个不同的线程同时进入此方法并传递两个不同的上下文时,我会导致此行出现死锁:results = [context executeFetchRequest:request error:&error];
有趣的是:似乎两个线程都无法在 Persistent Store Coordinator 上获取一些锁来执行获取请求。
我所有的上下文都是NSPrivateQueueConcurrencyType。
我无法解决问题,为什么我要锁定应用程序以及我应该采取哪些不同的做法。我对 Stack Overflow 的研究没有给我任何帮助,因为大多数人通过在 MOC 的队列上分派获取请求来修复所有锁,而我已经这样做了。
我将不胜感激有关此问题的任何信息。随时提供文档链接和其他长篇文章:我渴望了解更多关于各种并发问题和策略的信息。
【问题讨论】:
-
您能否提供代码:
currentUserPredicateInContext:和predicate构造(它们是否使用来自其他上下文的对象来构造)? -
你确定这是死锁吗?我建议你发布线程的堆栈跟踪
-
@DanShelly 这个错误很难重现,我今天没有发现它,所以没有堆栈跟踪。谓词的格式为“owner = %@”,其中 %@ 是来自用户默认值的字符串。我根本没有在谓词中使用任何 MObject。我确信这是一个死锁,因为在堆栈跟踪中,我的两个线程卡在 mutex_wait 上,这是调用 executeFetchRequest 的结果。
-
您使用类方法的任何原因。这可能是你的问题。
-
我们遇到了这个问题,我们最终承认失败。我们将其更改为使用
performBlock:并使用异步 API(完成块)。
标签: ios multithreading core-data concurrency deadlock