7

我们有一个已有数年历史的代码库,所有原始开发人员早已不复存在。它使用很多很多线程,但没有明显的设计或通用的架构原则。每个开发人员都有自己的多线程编程风格,因此一些线程使用队列相互通信,一些使用互斥锁锁定数据,一些使用信号量锁定,一些使用操作系统 IPC 机制进行进程内通信。没有设计文档,评论也很少。这是一团糟,似乎每当我们尝试重构代码或添加新功能时,都会引入死锁或其他问题。

那么,有没有人知道任何有助于分析和记录线程之间所有交互的工具或技术?FWIW,代码库是 Linux 上的 C++,但我有兴趣了解其他环境的工具。


更新

我很欣赏到目前为止收到的回复,但我希望得到比基本上是“添加日志消息、弄清楚发生了什么并修复它”的建议更复杂或更系统的东西。有很多工具可以用来分析和记录单线程程序中的控制流。多线程程序没有可用的东西吗?


另请参阅调试多线程应用程序

4

7 回答 7

6

购买一份英特尔的VTune及其线程分析工具。它将为您提供线程行为的系统和源级别视图。它当然不会为您自动记录事情,但至少在可视化不同情况下发生的事情方面应该是一个真正的帮助。

我认为您可以下载试用版,因此值得一试。我只使用过 Windows 版本,但是查看 VTune 网页它也有 Linux 版本。

于 2008-08-21T18:38:14.323 回答
4

作为一个起点,我很想在应用程序的关键点添加跟踪日志消息。这将允许你分析你的线程是如何交互的,而不会有观察线程的行为会改变它们的行为的危险(就像逐步调试的情况一样)。我的经验是使用 .NET 平台,我最喜欢的日志记录工具是 log4net,因为它是免费的,具有广泛的配置选项,并且如果您对实现日志记录的方式很明智,那么它不会明显影响应用程序的性能。或者,在 System.Diagnostics 命名空间中有 .NET 的内置调试(或跟踪)类。

于 2008-08-13T15:33:28.900 回答
3

我会首先关注共享内存锁(互斥锁和信号量),因为它们最有可能导致问题。查看哪个状态被锁保护,然后确定哪个状态受到几个锁的保护。这会让你感觉到潜在的冲突。查看持有锁的代码调用方法的情况(不要忘记虚拟方法)。尽量消除这些调用(通过减少持有锁的时间)。

给定持有的互斥锁列表和它们保护的状态的粗略概念,分配一个锁定顺序(即,互斥锁 A 应始终在互斥锁 B 之前使用)。尝试在代码中强制执行此操作。

如果不会对并发性产生不利影响,请查看是否可以将多个锁合二为一。例如,如果互斥锁 A 和 B 看起来可能有死锁,并且排序方案不容易完成,那么最初将它们组合成一个锁。

这并不容易,但我以牺牲并发性为代价来简化代码以解决问题。

于 2008-08-13T20:41:07.983 回答
2

对于自动化工具来说,这是一个非常困难的问题。您可能想查看模型检查您的代码。不要期望神奇的结果:模型检查器在代码量和它们可以有效检查的线程数方面非常有限。

可能对您有用的工具是CHESS(尽管不幸的是它仅适用于 Windows)。BLAST是另一个相当强大的工具,但很难使用并且可能无法处理 C++。维基百科还列出了我以前从未听说过的StEAM,但听起来它可能对你有用:

StEAM 是 C++ 的模型检查器。它检测死锁、分段错误、超出范围的变量和非终止循环。

或者,尝试将代码收敛到少量定义良好(最好是高级)的同步方案可能会有很大帮助。在同一个代码库中混合锁、信号量和监视器是自找麻烦。

于 2008-08-21T19:11:07.350 回答
1

使用 log4net 或类似工具要记住的一件事是它们会改变应用程序的时间,并且通常可以隐藏底层的竞争条件。我们有一些写得很糟糕的代码要调试并引入了日志记录,这实际上消除了竞争条件和死锁(或大大降低了它们的频率)。

于 2008-08-13T20:27:23.190 回答
1

在 Java 中,您可以选择 FindBugs(用于静态字节码分析)来查找某些类型的不一致同步,也可以选择来自 Coverity、JProbe、OptimizeIt 等公司的许多动态线程分析器。

于 2008-09-22T02:19:57.723 回答
1

UML 不能在这里帮助你吗?

如果您将代码库逆向工程为UML,那么您应该能够绘制显示类之间关系的类图。从方法是线程入口点的类开始,您可以看到哪个线程使用哪个类。根据我使用Rational Rose的经验,这可以通过拖放来实现;如果添加的类与之前的类之间没有关系,则添加的类不会被以您开始图表的方法开始的线程直接使用。这应该为您提供有关每个线程的作用的提示。

这还将显示共享的“数据对象”和特定于线程的对象。

如果您绘制一个大类图并删除所有“数据对象”,那么您应该能够将该图布局为云,每个云都是一个线程 - 或一组线程,除非代码库的耦合和内聚是可怕。

这只会给你一个难题的一部分,但它可能会有所帮助;我只是希望你的代码库不是太混乱或太“程序化”,在这种情况下......

于 2008-09-26T14:25:16.313 回答