要回答您的确切问题:“我还可以使用或查看什么来检查这些死锁的原因或如何防止这些死锁发生?”,我只能用一些非常普遍的想法来回答,因为问题你正在接近很难:
- 从您认为可能发生锁定的任何地方添加 NSLog 语句。我发现 using
NSLog(@"%s ...YOUR DEBUG STATEMENT", __PRETTY_FUNCTION__)
可以帮助您准确识别正在调用哪个函数,以及从哪个队列执行它。
如果我们超越了可用工具的问题(基本上没有什么用处),那么我会留下一些关于如何调试您描述的系统的建议:
作为背景知识:我已经构建了平滑滚动的 UITableViews,其中包含 2000 多个动态下载和显示的可变高度单元格,其中包含绝对没有由于数据处理或绘图而导致的抖动或延迟的图像。该系统最初是使用 CoreData 设计的,但最终我们直接使用 SQLite 来解决您在多线程和并行性方面遇到的问题。我并不是在提倡切换到 SQLite——这是我们在内部做出的一个决定,目的是提高速度并减少本地数据库中的不一致性。我将此作为我回答的上下文。
我将首先仔细研究您对 Grand Central Dispatch 的使用。如果您使用任何 dispatch_sync 调用,请确保它们不会出现在阻塞操作线程的链中。我这样做最初是为了确保多个线程不会同时访问一个托管对象上下文,并且在调试几个小时后才发现问题。这些可能会偷偷摸摸,因为 dispatch_sync 调用可能在其他函数调用的函数中很深。
我最终确实使用了一个事务系统(非常 SQL-y),它为单个查询/更新动态创建了队列,这将确保一次不会发生太多操作。我还有一个完全不同的系统,它将使用单独的串行读取队列来快速读取数据库。如果可能,该队列的 MOC 将从其他 MOC 镜像。这很重,而且相对来说非常慢。由于系统主要在后台线程上处理,因此与用户隔离。
CoreData 通常很难多线程。SQLite 稍微简单一些,尽管您必须围绕它构建许多特定于应用程序的架构才能使其可用。
如果您想发布有关您的系统的更多详细信息,我可能会提供更具体的帮助。希望这有用。