问题:我如何让核心日期合并在两个不同线程中对同一NSManagedObject
所做的更改?线程更改不同的属性,并且这些属性的任意组合都是有效的。核心数据和竞赛条件
有一个应用程序(至少)有两个线程,UI线程和后台线程。 所谓的Document
是NSManagedObject
的子类。 A Document
有三个属性,attrA
,attrB
和attrC
。
的后台线程读取attrA
和写入attrB
,如:
doc.attbB = md5(doc.attrA);
(实际上,它是更复杂,更费时,但你的想法)。
的UI线程显示所有attrA
,attrB
和attrC
给用户,并允许用户更改attrA
和attrC
。 (有些同时attrB
值无效。)
我强调的是,只有UI线程写入attrA
,只有后台线程写入attrB
。
现在,用户在attrB
计算完成之前更改attrC
。 后台线程尝试保存attrB
并出现错误。 我现在所做的是:
if(!saved) {
// I did try to check that it's *that* kind of error,
// but that's iOS5-specific, while I need 4.3
// (comments on error type checking in 4.3 are welcome).
// Anyway, finally it was this:
id tmp = doc.attrB;
[[doc managedObjectContext] refreshObject:doc mergeChanges:NO];
doc.attrB = tmp;
BOOL saved = [context save:&error];
// NSLog if it still failed
}
在一般情况下,这是不行的。
起初,会发生什么,如果更多的变化将这些线之间进行:
[[doc managedObjectContext] refreshObject:doc mergeChanges:NO];
doc.attrB = tmp;
// more changes happen here!!!
BOOL saved = [context save:&error];
是的,我能如果一段时间,但它不是一般情况下的解决方案取代。如果这些变化反复发生,这可能是一个无限循环。
第二,UI线程也可能试图保存一些东西。在我看到的旨在合并更改代码的类之一,
#pragma mark Changes Propagation
- (void)__contextDidSave:(NSNotification*)notification
{
[parent performSelectorOnMainThread:@selector(__mergeChanges:) withObject:notification waitUntilDone:NO];
}
- (void)__mergeChanges:(NSNotification*)notification
{
[objectContext mergeChangesFromContextDidSaveNotification:notification];
if (parent) {
[parent __mergeChanges:notification];
}
}
据我了解,__mergeChanges
将正确的线程上运行,但不会立即;这是可能的UI线程将试图挽救改变attrB
的后台线程后的变化attrA
和attrC
但__mergeChanges
之前运行。
这是一个典型的竞赛条件。
问题:我如何正确使核心日期合并在两个不同线程中对同一NSManagedObject
所做的更改? (线程更改不同的属性,并且这些属性的任意组合都是有效的,但核心数据不知道这一点。)
两个不同的线程有两个不同的'NSManagedObject's。也就是说,我无法将它们用于锁定。也就是说,我需要一个全局锁。第二,范围是什么?除非我错过了一些东西,它看起来像是将一个保存包装到'@ synchronized'中不会有任何好处。而且,我如何将通知包装到'@ synchronized'中?应该有一整章的同步,但由于某种原因我找不到它。我希望这不是因为它不在那里。 – 18446744073709551615