我遇到了竞争条件,我不知道如何解决它。 getPurchasedBookTitles和getBookEntryIDs使用NSOperationQueue在不同的线程中,它们相互竞争调用fetchBooks(这是一个不同类的方法)。我把managedObjecContext(parent,child,root)用lock / unlock来避免赛车问题,但它似乎没有解决根问题。
问题是for循环中的book.bookTitle(所有书籍中的Book * book)将在某个时候变为nil并导致应用程序崩溃或挂起。
提前致谢!
//在单件类中,dispatch_once
- (NSArray *)getPurchasedBookTitles
{
NSMutableArray *bookTitles = [[NSMutableArray alloc] init];
NSArray *allBooks = [[CoreDataManager sharedInstance] fetchBooks];
for (Book *book in allBooks)
{
if (book.bookTitle != nil && book.is_owned != nil )
if (![bookTitles containsObject:book.bookTitle] && [[book is_owned] boolValue] == YES)
[bookTitles addObject:book.bookTitle];
}
return bookTitles;
}
- (NSArray *)getBookEntryIDs
{
NSMutableArray *bookTitles = [[NSMutableArray alloc] init];
NSArray *allBooks = [[CoreDataManager sharedInstance] fetchBooks];
for (Book *book in allBooks)
{
if (book.bookTitle != nil)
if (![bookTitles containsObject:book.bookTitle])
[bookTitles addObject:book.bookTitle];
}
return bookTitles;
}
//在类coreDataManager中 // managedObjectContextChild,managedObjectContext,writerManagedObjectContext在appDelegate和coreDataManager类中详细声明和实例化。
- (NSArray *)fetchBooks
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"bookTitle" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:bookEntity];
[request setPredicate:nil];
[request setSortDescriptors:sortDescriptors];
[managedObjectContextChild lock];
[managedObjectContext lock];
[writerManagedObjectContext lock];
NSError *error = NULL;
NSArray *results = [managedObjectContextChild executeFetchRequest:request error:&error];
if (error != NULL)
NSLog(@"Error fetching - %@", error);
[writerManagedObjectContext unlock];
[managedObjectContext unlock];
[managedObjectContextChild unlock];
return results;
}
答案 0 :(得分:2)
核心数据不是线程安全的,您需要采取措施来解决这个问题。我不确定将bookTitle
设置为nil是什么,但上面的代码有几个主要问题:
“非线程安全”意味着您无法在多个线程上使用所有核心数据对象,除非您可以保证所有访问都是同步的。通过锁同步获取仅覆盖部分内容 - 您不能同时在多个线程上使用获取的对象。您将在多个线程上使用相同的Book
实例,这几乎可以保证问题。通常的方法是为不同的线程/队列提供自己的托管对象上下文,并在更改时同步更改。
锁定可能会有所帮助,但前提是你确定你已经发现了所有可能性。很难做到正确并容易陷入僵局。这就是为什么Core Data包含专门用于处理这种情况的API的原因。在此处查看performBlock
和performBlockAndWait
方法以获取帮助。使用它们而不是你自己的锁定方案。