我是CoreData的新手,我正在尝试创建一个简单的应用程序。
假设我有一个功能:
func saveEntry(entry: Entry) {
let moc = NSManagedObjectContext(concurrencyType: .NSPrivateQueueConcurrencyType)
moc.parentContext = savingContext
moc.pefrormBlockAndWait {
// find if MOC has entry
// if not => create
// else => update
// saving logic here
}
}
它可能会引入一个问题:如果我从两个线程调用saveEntry
,传递相同的条目就会复制它。所以我已经将串行队列添加到我的数据库适配器并按以下方式执行:
func saveEntry(entry: Entry) {
dispatch_sync(serialDbQueue) { // (1)
let moc = NSManagedObjectContext(concurrencyType: .NSPrivateQueueConcurrencyType)
moc.parentContext = savingContext
moc.pefrormBlockAndWait { // (2)
// find if MOC has entry
// if not => create
// else => update
// saving logic here
}
}
}
它工作正常,直到我想添加另一个接口函数:
func saveEntries(entries: [Entry]) {
dispatch_sync(serialDbQueue) { // (3)
let moc = NSManagedObjectContext(concurrencyType: .NSPrivateQueueConcurrencyType)
moc.parentContext = savingContext
moc.pefrormBlockAndWait {
entries.forEach { saveEntry($0) }
}
}
}
现在我遇到了死锁:1将在serialDbQueue上调用并等到保存结束。将在私人队列上调用2并将等待3.而3正在等待1。
那么处理同步访问的正确方法是什么?据我所知,由于此处所述的原因,保留一个MOC并对其执行保存是不安全的:http://saulmora.com/coredata/magicalrecord/2013/09/15/why-contextforcurrentthread-doesn-t-work-in-magicalrecord.html
答案 0 :(得分:1)
我会尝试用一个NSManagedObjectContext
作为控制机制来实现它。每个上下文都维护一个串行操作队列,因此多个线程可以调用performBlock:
或performBlockAndWait:
而不会有任何并发访问的危险(尽管您必须小心上下文的数据在块入队的时间和时间之间的变化最终执行)。只要上下文中的所有工作都在正确的队列上完成(通过performBlock
),就不会有从多个线程中排队工作的内在危险。
当然有一些复杂因素需要考虑,如果不了解您的应用程序,我无法提供真正的建议。