我正在使用Core Data unique attributes中描述的方法来防止两次使用相同的属性(此处属性称为ID)。
这在单线程环境中工作正常。我使用多线程环境并使用每个线程范例的一个上下文。
问题是如果两个线程同时尝试创建具有相同属性的对象,则存在以下问题:
您发现自己有两个具有相同ID(1)的记录。
我在测试时看到了这个问题,所以很少见,但肯定会随着时间的推移而发生。
当然,有很多选项,比如GDC,信号量可以防止这种情况发生,但在使用复杂的解决方案之前,我想知道是否有人有更好的解决方案,或者可以建议在什么级别来序列化事件。 / p>
使用iOS5 +和ARC。
我使用此代码来同步我的上下文:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
和
- (void)backgroundContextDidSave:(NSNotification *)notification {
/* Make sure we're on the main thread when updating the main context */
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:NO];
return;
}
/* merge in the changes to the main context */
for (NSManagedObjectContext* context in [self.threadsDictionary allValues]){
[context mergeChangesFromContextDidSaveNotification:notification];
}
}
获取线程安全的上下文:
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *) managedObjectContextForThread {
// Per thread, give one back
NSString* threadName = [NSString stringWithFormat:@"%d",[NSThread currentThread].hash];
NSManagedObjectContext * existingContext = [self.threadsDictionary objectForKey:threadName];
if (existingContext==nil){
existingContext = [[NSManagedObjectContext alloc] init];
[existingContext setPersistentStoreCoordinator: [self persistentStoreCoordinator]];
[self.threadsDictionary setValue:existingContext forKey:threadName];
[existingContext setMergePolicy:NSOverwriteMergePolicy];
}
return existingContext;
}
答案 0 :(得分:0)
我认为我找到了解决方案,仅使用Core Data。
我现在正在使用NSLock来锁定上下文以模拟某种事务:
[[self managedObjectContextForThread] tryLock];
... read if ID1 exists ...
... write ID1 ...
[[self managedObjectContextForThread] unlock];
这似乎解决了这个问题(暂时)。