多线程调试技术

Mau*_*Mau 6 .net debugging multithreading

我想知道是否有人知道对多线程应用程序的调试技术的一个很好的调查.理想情况下,我正在寻找基于案例的分析:死锁,饥饿,共享状态损坏,......

.Net特定的,或通用的.

Ste*_*ary 11

我不知道有哪篇文章或书籍可以解决您正在寻找的内容,因此这是我在Windows上进行12年多线程调试(非托管和托管)的"经验教训".

正如我在评论中所述,我的大多数"多线程调试"实际上是通过手动代码审查完成的,并且正在寻找这些问题.

死锁和共享状态损坏

文档锁定层次结构(它们保护的顺序和共享状态),并确保它们是一致的.这解决了大多数死锁问题和损坏的共享状态问题.

(注意:上面的"锁定层次结构"链接指的是Herb Sutter的Dr. Dobbs文章;他撰写了一系列我强烈推荐的有效并发文章).

更多关于死锁的信息

使用RAII进行所有同步.这可确保在异常情况下释放锁定.首选"lock"语句尝试/ finally.

(请注意,.NET中的RAII取决于IDisposable,而不是Finalize,并假设客户端代码将正确使用using块).

饥饿

删除线程优先级的任何修改.正确的优先级实际上有点反直觉:最好给线程最大的工作来做较低的优先级,并为I/O绑定的线程(包括UI线程)提供更高的优先级.由于Windows自动执行此操作(请参阅Windows Internals),因此根本没有理由让代码参与进来.

一般来说

删除内部编写的所有无锁代码.它几乎肯定包含微妙的错误.将其替换为.NET 4无锁集合同步对象,或将代码更改为基于锁定.

使用更高级别的概念进行同步.该任务并行库统一取消在.NET 4中删除几乎任何需要的直接使用ManualResetEvent,Monitor,Semaphore,等.

使用更高级别的概念进行并行化..NET 4中的TPL和PLINQ具有内置的自平衡算法,并具有智能分区和工作窃取队列,可自动提供最佳的并行化.对于极少数情况下自动并行化是次优的,TPL和PLINQ都暴露了大量可调整的旋钮(自定义分区方案,长时间运行的操作标志等).

我发现还有一种技术可用于任何具有不同线程调用方法的类:记录哪些方法在哪些线程上运行.通常,这会作为注释添加到方法的顶部.确保每个方法仅在已知的线程上下文中运行(例如,"在UI线程上"或"在ThreadPool线程上"或"在专用后台线程上").除非您正在编写同步类(并且如果您正在编写同步类,请问自己是否真的应该这样做),这些方法都不应该说"在任何线程上".

最后,命名您的线程.这有助于在使用VS调试器时轻松区分它们..NET通过Thread.Name属性支持此功能.


Dan*_*ner 6

不是你要求的,但也许你会发现CHESS很有趣.