分析多线程程序

时间:2020-03-05 18:39:24  来源:igfitidea点击:

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

那么,是否有人知道任何有助于分析和记录线程之间所有交互作用的工具或者技术? FWIW,代码库是Linux上的C ++,但是我很想听听其他环境的工具。

更新

我很感谢到目前为止收到的答复,但是我希望有一些比建议更复杂或者更系统的建议,它实质上是"添加日志消息,弄清楚正在发生的事情,并加以解决"。有很多工具可以分析和记录单线程程序中的控制流。多线程程序没有可用的东西吗?

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

解决方案

回答

首先,我很想在应用程序中的战略要点添加跟踪日志消息。这将使我们能够分析线程如何进行交互,而没有观察线程会改变其行为的危险(分步调试可能就是这种情况)。
我的经验是使用.NET平台,我偏爱的日志记录工具是log4net,因为它是免费的,具有广泛的配置选项,并且,如果我们对实现日志记录的方式很明智,那么它不会明显影响应用程序的性能。或者,在System.Diagnostics命名空间中有.NET的内置Debug(或者Trace)类。

回答

使用log4net或者类似工具要记住的一件事是,它们会更改应用程序的时间,并且通常会隐藏潜在的竞争条件。我们有一些编写不良的代码来调试和引入日志记录,这实际上消除了竞争条件和死锁(或者大大降低了它们的发生频率)。

回答

我将首先关注共享内存锁(互斥锁和信号灯),因为它们最有可能引起问题。查看哪个状态受锁保护,然后确定哪个状态受多个锁保护。这会让我们有潜在的冲突感。查看持有锁的代码调用方法的情况(不要忘记虚拟方法)。尝试在可能的情况下消除这些呼叫(通过减少持有锁定的时间)。

给定所持有的互斥锁的列表以及它们保护的状态的大致概念,请分配锁定顺序(即,始终应在互斥锁B之前获取互斥锁A)。尝试在代码中强制执行此操作。

如果并发不会受到不利影响,请查看是否可以将多个锁合并为一个。例如,如果互斥锁A和B看起来好像有死锁,并且排序方案不容易完成,则可以将它们最初组合为一个锁。

这不是一件容易的事,但是我要简化代码,但要以并发为代价来解决问题。

回答

购买英特尔VTune及其线程配置工具的副本。它将为我们提供线程行为的系统视图和源代码视图。当然不会自动为我们记录事物,但至少在可视化不同情况下的发生时,它应该是真正的帮助。

我认为我们可以下载试用版,因此值得一试。我只使用Windows版本,但在VTune网页上也有Linux版本。

回答

对于自动化工具来说,这确实是一个难题。我们可能需要研究模型检查代码。不要指望神奇的结果:模型检查器在代码数量和它们可以有效检查的线程数量方面非常有限。

CHESS是一个可能适合工具(尽管很遗憾,它仅适用于Windows)。 BLAST是另一个功能相当强大的工具,但是非常难以使用,可能无法处理C ++。 Wikipedia还列出了StEAM,我之前从未听说过,但听起来它可能对我们有用:

StEAM is a model checker for C++. It detects deadlocks, segmentation faults, out of range variables and non-terminating loops.

替代地,尝试将代码朝着少量的明确定义的(最好是高级)同步方案进行收敛可能会大有帮助。在同一代码库中混合使用锁,信号量和监视器会带来麻烦。

回答

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

回答

UML不能在这里吗?

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

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

如果我们绘制一个大的类图并删除所有"数据对象",那么我们应该能够将该图布置为云,每个云都是一个线程或者一组线程,除非代码库的耦合和内聚非常糟糕。

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