多个NSManagedObjectContexts - 防止竞争条件和死锁

时间:2014-12-02 22:54:10

标签: ios multithreading core-data concurrency nsmanagedobjectcontext

我已经阅读了大量关于后台核心数据流程的博客,但我并没有更接近理解如何最好地管理许多BG核心数据任务同时解雇并通知未定义的主线程MOC时间。

我知道你应该每NSManagedObjectContext有一个NSThread,并且通过订阅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吗?这样,如果我知道其他任务正在运行,我可以存储通知并按照它们实例化的顺序处理它们以确保没有数据被覆盖?

1 个答案:

答案 0 :(得分:15)

  1. 建议每个线程使用一个MOC。有一些例外,但一般规则仍然有效。不要创建NSThread对象。只是不要。太痛苦了。而是使用块或NSOperation实例。它们更易于克服并保护您免受很多痛苦。

  2. 不要使用带有Core Data的锁。正确使用时,Core Data会自行锁定,如果你在周围扔锁,则会导致问题。理想情况下,您应该从不需要在现代Objective-C中自行调用锁。

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

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

    • 您有一个主线程/ UI MOC。这是你唯一的事实来源。您的UI从中提供并写入。
    • 任何后台流程都是在NSOperation或类似的构造中完成的。您在此构造内部创建了一个MOC,它是主要上下文的上下文。
    • 保存子项时,更改将合并到父项(即UI MOC)。
    • 设置适用于主MOC的合并策略。如果您认为您需要针对不同情况制定不同的政策,那么您应该重新考虑自己的工作方式。

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

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

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

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