【问题标题】:What are the restrictions between core data parents' concurency type and child concurency type in core data?核心数据中核心数据父并发类型和子并发类型有什么限制?
【发布时间】:2013-01-27 17:58:55
【问题描述】:

它们应该相同吗?父级有什么样的并发类型?

每次子执行executeFetchRequest 时,都会询问父级。如果来自不同线程的多个子进程执行相同类型的 executeFetchRequest 会怎样?

如果父级被声明为主要并发类型,然后另一个线程上的子级执行executeFetchRequest,会发生什么?它会等到主线程运行,然后给出结果,然后继续线程吗?什么?

基本上我有各种等待锁定问题,我想了解更多。

实际上,如果网络上有关于多线程父子关系的常见做法的资源,我会感到震惊。在IOS5中我们需要做performBlock。我们是否需要在所有核心数据命令中都这样做,因为这意味着这里的代码会发生很多变化。

更新:

http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/Articles/cdConcurrency.html#//apple_ref/doc/uid/TP40003385-SW1 已经过时了吧?

【问题讨论】:

  • 与核心数据部分的并发性并没有完全过时。它详细说明了父/子上下文系统为您做了什么。它根本没有涵盖如何使用 parentContexts(它应该!)。

标签: core-data concurrency


【解决方案1】:

Core Data Release Notes 文档中列出了使用父/子上下文的详细信息,其中指出:

因此,您不能使用使用线程限制类型创建的父上下文(请参阅“Concurrency Support for Managed Object Contexts”)。

因此,要回答您的问题,父上下文的并发类型必须为 NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType。子上下文可以有任何并发​​类型。

如需全面了解和大量示例代码,请查看Marcus Zarra's Core Data video coursebeta version of his book

【讨论】:

  • 文档对此不太清楚。提到NSConfinementConcurrencyType,它首先说您不能将此并发类型与新的嵌套上下文功能结合使用。然后因此,您不能使用使用线程限制类型创建的父上下文。但是,是的,你是对的,恕我直言。确实 +1。
【解决方案2】:

除了WWDC 2012 videorelease notes 之外,Apple 没有发布任何关于父子上下文的真实文档。该视频非常详细地介绍了如何使用它们以及您可能需要使用 performBlock 或 performBlockAndWait 的极少数情况。

大多数人忽略的重要一点是并发类型是指上下文将使用哪个线程来访问核心数据堆栈的其余部分,而不是创建上下文的线程。您几乎不需要在自己的代码中使用 performBlock 或 performBlockAndWait只要您继续实现线程限制模式。这样做通常会触发死锁(尤其是当一个或多个上下文是 NSMainQueueConcurrencyType 时)。

NSMainQueueConcurrencyType - 适用于 UI 中使用的 NSManagedObjects。您应该只维护其中之一。

NSPrivateQueueConcurrencyType - 适用于后台操作。从外部文件或 Web 服务导入新对象时,parentContext 是主要的 UI 上下文。当您完成创建对象时,save 会自动通知 parentContext 更改。您还可以使用私有上下文作为 UI 上下文的父级,以便在不阻塞 UI 的情况下从磁盘加载和保存存储。

因此,如果您创建子上下文并执行提取请求,它会使用线程(由并发类型指定)与父上下文交互自动。它将自动适当地使用 performBlock。当您保存子上下文时,父上下文会自动获取合并的更改,而无需您对父上下文执行任何操作。

如果您必须使用 performBlock 或 performBlockAndWait,则不再使用线程限制模式。它在线程限制模式中唯一有效的情况是跨越“表亲”上下文,其中父级有多个子级,一个子级的更改保存到父级,父级将这些更改下推给其他子级。

【讨论】:

  • 我在没有 performBlock 的情况下出现了死锁。所以我尝试了 performBlock。
  • 该视频介绍了导致这些死锁的原因。基本上,上下文调用 performBlock 以便您与堆栈的其余部分进行通信。如果你想在它用来与核心数据堆栈的其余部分通信的线程上,你只使用 performBlock - 它独立于创建它的线程。
  • 根据Core Data Release Notes,您应该在performBlock:performBlockAndWait: 调用中执行任何涉及托管对象上下文或托管对象的工作。一个例外是,如果您在主线程上并且正在使用具有主队列并发类型的上下文。
  • @KrisMarkel 来自发行说明:“您可以使用限制模式使用上下文,就像在 OS X v10.7 和 iOS 5 之前一样。您可以直接发送上下文消息;这取决于您以确保您从正确的队列发送消息。”您可以将所有内容包装在块中,但仅当您可能跨线程进行通信时才需要它 - 并且可能导致死锁。 这意味着始终使用 performBlock 和 performBlockAndWait 会导致更多问题,而它在大多数用例中都可以解决
  • 约束并发类型确实如此,但使用它意味着以旧的且容易出错的方式处理并发。最好使用私有队列并发和 performBlock 方法。然后框架为您处理所有并发问题。
猜你喜欢
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多