【发布时间】:2015-03-31 20:19:04
【问题描述】:
我正在尝试将核心数据数据库迁移到 Realm(大约在 0-2 百万行之间),并且遇到了一个死锁,据我所知,这是不应该发生的。
从一个单例类,我像这样启动迁移:
_queue = dispatch_queue_create("DiagnosticMigrationQueue", NULL);
dispatch_async(_queue, ^{
_realmMigrator = [[CoreDataToRealmMigrator alloc] init];
[_realmMigrator performMigrationToRealm];
});
在performMigrationToRealm 方法中,我这样设置了Core Data 堆栈:
- (void) performMigrationToRealm
{
self.migrationIsRunning = YES;
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"persistentStore"];
NSError *error;
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
context.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[context.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:@"DiagnosticData"
URL:url
options:nil
error:&error];
了解检查:当我创建队列时,尚未设置任何 Core Data 堆栈。因此,NSManagedObjectContext 只在 GCD 决定放置我的块的任何线程上创建。
到目前为止,一切都很好。没问题。我现在运行一个方法 - 以 100,000 个批次 - 获取实体中的所有 NSManagedObjectIds。它看起来像这样:
for (NSInteger numberOfMigratedBatches = 0; numberOfMigratedBatches < totalNumberOfBatches; numberOfMigratedBatches++)
{
NSArray *samples = [context executeFetchRequest:fetchRequest error:&error];
if (samples && !error)
{
[self transferWeightSamplesToRealmWithObjectIds:samples withContext:context];
}
[context reset];
fetchRequest.fetchOffset = batchSize * (numberOfMigratedBatches+1);
}
上面代码块中的fetchRequest 是时髦的行。即使我已经在串行队列上启动了这个过程,我还是以某种方式结束了这个:
这些 minion_duties2 线程中的每一个都卡在同一行代码上,即上面的 fetchRequest。
这里发生了什么?我了解队列!= 线程,并且 GDC 会将我的代码放在任何认为合适的线程上。但是,我不希望它会将我的代码放在三个线程上。另外,com.apple.root.user-initiated-qos.overcommit 是什么?我会说这是过度使用。我只希望这段代码运行一次!
【问题讨论】:
-
据我所知,您的代码看起来不错。如果我不得不猜测,我会说:这是几个不同的 fetchRequests 试图在几个不同的线程上执行可能导致死锁。您是否有任何理由手动进行批处理,而不是通过在 NSFetchRequest 上设置 fetchBatchSize 属性让 Core Data 为您完成?
-
Emm.. 可能是我的疏忽。我之前没有做过很多需要批处理的 fetchRequest,所以我没有意识到 Core Data 可以为我完成。
标签: ios multithreading core-data deadlock realm