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

Mag*_*goo 2 concurrency multithreading core-data nsmanagedobjectcontext ios

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

我知道你应该有1 NSManagedObjectContextNSThread和那个通过订阅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并将我的所有Core Data工作到它上面吗?那样我可以让一个MOC与自己同步工作吗?

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

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

Mar*_*rra 15

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

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

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

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

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

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

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

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

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