核心数据 - 多线程 - 启动时的竞争条件

时间:2012-01-26 10:29:35

标签: iphone multithreading core-data nsmanagedobjectcontext race-condition

我有一个使用Core Data的多线程应用。我在启动时遇到了很多崩溃,以及各种奇怪的错误消息。但是,有时它工作正常!我从未在自己的iPhone4上看到过崩溃,但它在其他设备上崩溃了。我想我已经找到了问题,但我不确定如何最好地解决它。

当应用程序启动时,我使用GCD从Web下载数据并在后台线程上更新核心数据。在主线程上,我继续设置表视图,其中一个命令触发NSManagedObjectContext getter。我几乎使用标准模板代码,因此这是第一次运行时,通常的惰性实例代码会创建NSPersistentStoreCoordinator

然而,后台线程正在创建一个新的NSManagedObjectContext供自己使用。这包括获取NSPersistentStoreCoordinator如下:

    // Create a new NSManagedObjectContext for this thread
    NSManagedObjectContext *threadContext = nil;
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        threadContext = [[NSManagedObjectContext alloc] init];
        [threadContext setPersistentStoreCoordinator:coordinator];
        NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
        [threadContext setMergePolicy:mergePolicy];
    } else {
        NSLog(@"Error - No NSPersistentStoreCoordinator");
    }

我90%肯定这个问题是两个线程同时进入NSPersistentStoreCoordinator代码。两个线程都认为对象是nil,因此创建对象。这导致第一个线程到达那里的问题,因为ivar突然指向错误的位置。那时坏事就发生了!

那么如何最好地解决这个问题呢?我通过向后台线程添加sleep(1)暂时解决了这个问题:)但我不确定这是否是最好的解决方案!我已经尝试更改NSPersistentStoreCoordinator属性,以便它们是原子的,但这没有帮助。我应该将@synchronise中的每个标准getter包装到互斥锁中吗?我还没有时间尝试这个,但它应该停止两个线程运行相同的代码。或者有更好的方法吗?

思想?

谢谢克雷格

======================================

有关信息,以下是我看到的一些错误和崩溃。这些都是随机的,但它可能会帮助其他人在将来找到这篇文章。

  

2012-01-18 22:19:57.586 CBF [10468:11d03] - [NSSQLModel   _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6b80390

     

2012-01-18 22:19:57.595 CBF [10468:11d03] * 终止应用程序   未捕获的异常'NSInvalidArgumentException',原因:' - [NSSQLModel   _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6b80390'

     

2012-01-19 16:58:06.671 CBF [11738:fe03] - [__ NSCFDictionary   _hasPrecomputedKeyOrder]:无法识别的选择器发送到实例0x6d55040

     

2012-01-25 21:45:31.174 CBF [16911:1310b] - [__ NSArrayM   _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6d59370

     

2012-01-25 21:45:31.175 CBF [16911:1310b] * 终止应用程序   未捕获的异常'NSInvalidArgumentException',原因:' - [__ NSArrayM   _addPersistentStore:identifier:]:无法识别的选择器发送到实例0x6d59370'

1 个答案:

答案 0 :(得分:4)

为什么不删除延迟实例化,而是在应用启动时立即创建协调器?