【问题标题】:Multiple NSManagedObjectContexts - preventing race conditions and deadlocks多个 NSManagedObjectContexts - 防止竞争条件和死锁
【发布时间】:2014-12-02 22:54:09
【问题描述】:

我已经阅读了大量关于后台核心数据进程的博客,但我还没有更深入地了解如何最好地管理许多同时触发的 BG 核心数据任务并在未定义的情况下通知主线程 MOC时间。

我知道每个 NSThread 应该有 1 个 NSManagedObjectContext,并且通过订阅 NSManagedObjectContextDidSaveNotification 以及使用 [context performBlock 我可以完成一些不错的异步任务。

也就是说,我正在异步运行很多任务,我不能 100% 知道一些任务何时会重叠,并且我观察到了以下形式的竞争条件......

  • BG MOC 1 开始执行任务
  • BG MOC 2 开始执行任务
  • BG MOC 2 完成任务并发送保存通知
  • BG MOC 1 完成任务并随后擦除 BG MOC 2s 更改

我的总体问题是如何解决多个 MOC 中的竞争条件?

  1. 如果正确的行为是每个线程有 1 个 MOC。我可以创建一个 NSThread ivar 并将我的所有核心数据工作放在上面吗?这样我就可以拥有一个与自身同步工作的 MOC?

  2. 我读过 NSLock 可能是避免同时从多个线程访问某些代码的解决方案。但我不知道我应该锁定什么?保存上下文方法?持久存储(似乎使多线程毫无意义)?

  3. 最后,我可以标记/编号/命名我的 MOC 吗?这样,如果我知道其他任务正在运行,我可以存储通知并按照它们被实例化的顺序处理它们,以确保没有数据被覆盖?

【问题讨论】:

    标签: ios multithreading core-data concurrency nsmanagedobjectcontext


    【解决方案1】:
    1. 建议每个线程一个 MOC。有例外,但一般规则仍然成立。不要创建 NSThread 对象。只是不要。太痛苦了。而是使用块或 NSOperation 实例。它们更容易摸索并保护您免受很多痛苦。

    2. 不要对 Core Data 使用锁。如果使用得当,Core Data 会进行自己的锁定,如果你在周围乱扔锁,就会导致问题。理想情况下,您应该永远在现代 Objective-C 中自己调用 lock。

    3. 除了具有 ivar 或属性引用之外,您不能命名 MOC。你也不应该需要。

    使用 Core Data 进行多线程的最简洁方法如下:

    • 您有一个主线程/UI MOC。那是你唯一的真理来源。您的 UI 会从中获取数据并写入数据。
    • 任何后台进程都在 NSOperation 或类似结构中完成。您在此构造中创建一个 MOC,它是主上下文的 上下文。
    • 保存子项时,更改将合并到父项(即 UI MOC)。
    • 设置适合您的主 MOC 的合并策略。如果您认为需要针对不同情况制定不同的政策,那么您应该重新审视自己的工作方式。

    理想情况下,每个后台进程都应该是一个数据孤岛,可以独立运行而不会与另一个进程发生冲突。如果您有冲突,那么这是您需要在业务逻辑中解决的合并问题。

    如果您遇到两个后台操作将命中同一条数据的情况,那么您应该按顺序运行它们,而不是并行运行。对相同数据的并行编辑是等待发生的痛苦,不要这样做。

    您可以通过使用NSOperationQueue 实例来控制事情是顺序的还是并行的。

    遵循这些规则,您将不会遇到竞争条件或死锁。

    【讨论】:

    • 很好的答案,非常感谢。我没有在我的实现中使用NSOperation / NSOperationQueue,所以我将从那里开始。很高兴对我所有狡猾的想法都坚决反对。
    • “NSOperation 或类似的构造。你创建一个 MOC 而不是这个构造”应该是“这个构造的内部”吗?
    • 我假设使用 GCD 算作“类似构造”,只要每个 MOC 及其对象只能从其自己的串行队列访问,一切都很好,不是吗? NSOperationQueue.
    • 你说 GCD 是一个“相似的结构”是正确的。然而,NSOperations 有几个好处,包括可维护性(单独的类文件更容易维护)和取消操作的能力。还有其他好处,但这是一个较长的讨论。
    • "如果您遇到两个后台操作将命中同一条数据的情况,那么您应该按顺序运行它们,而不是并行运行。对同一数据进行并行编辑是等待发生的痛苦,不要这样做。”伟大的洞察力。正在尝试实现这方面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 2012-10-27
    • 2016-03-21
    • 1970-01-01
    • 2015-01-16
    相关资源
    最近更新 更多