如何证明多线程有效?

时间:2009-10-05 14:47:36

标签: c# multithreading testing

如何证明多线程在我的C#程序中有效?这是针对测试要求的。例如,我将不得不为记录器类添加一些锁定(是的,我知道,我不应该编写自己的日志记录类),我需要一个测试用例来证明更改是有效的。

8 个答案:

答案 0 :(得分:7)

如果要测试锁定代码是否正确同步对日志的访问,则需要构建可确保争用的测试。这可能需要您重构代码,以便您可以注入一个模拟日志编写器类,该类可以在任意时间段内保存日志锁。

这是一个广泛的主题,你可以在StackOverflow上找到几个相关的问题,这些都值得一读:

CHESS是一个正在开发的框架,用于识别“断言违规,死锁,活锁,数据争用和内存模型错误”。我实际上并没有使用它,但看起来它可能非常有用。

答案 1 :(得分:5)

嗯,这可能听起来不对,但事实是你不能证明单元测试的多线程行为。话虽如此,您可以通过测试获得对代码的信心,并且随着时间的推移它可能实际上存在问题。

<咆哮> 在许多项目中,多线程代码是我存在的祸根。通常,人/开发人员没有做好工作所需的专业知识。在任何人在野外看到它之前,虫子经常被忽视很长一段时间,然后你无法重现这个问题以确定最新情况。此外,尝试通过调试“修复”损坏的多线程代码通常不是一种可行的方法。 < /咆哮>

无论如何,继续进行测试,做这么多并没有什么坏处,这很容易做到。只需启动N个线程,让它们等待一个ManualRestEvent,然后在一个紧凑的循环中调用你的api几十万次:)。 但首先我会建议团队中的每个人都进行代码审核。每行代码都会考虑并行执行代码。问问自己:

  1. 我真的需要这个锁()吗?
  2. lock()中必须包含的代码量是多少?
  3. 我可以使这个对象/状态不可变并避免锁定吗?
  4. 调用者是否有办法在锁内执行代码?
  5. 查看锁定内的所有访问和更改的成员是否为“volatile”?
  6. 您是否正确使用System.Threading.Thread.MemoryBarrier?
  7. 如果涉及多个锁,它们总是以相同的顺序获得吗?
  8. [wiki add here]

答案 2 :(得分:1)

你真的不能:)这一切都取决于时间,它可能随时爆炸。你必须在心理上检查每一种可能的情况,这是唯一的方法。这就是为什么许多开发人员认为多线程是不可能正确的。

答案 3 :(得分:1)

+1给另一个建议使用Thread.Sleep()

的人

我实际上发现Thread.Sleep()对于模拟各种不同的竞争条件非常有用。但是,出于显而易见的原因,您需要确保在部署到生产环境之前删除(或使用配置以禁用)Thread.Sleep。

在Robert C Martin的书“清洁代码”中,他建议在单元测试中使用“摇摆策略”以找出多线程问题。 “Jiggling”涉及向代码添加随机等待时间,以便线程在不同时间以不同顺序运行。然后,您可以多次运行单元测试,并且您的摇晃可能会导致一些缺陷。重要的是不要忽略涉及多线程的任何单元测试失败,因为它们在下次运行测试时会通过。

Rant:我不确定为什么有人会拒绝投票给另一个答案,这个答案建议使用Thread.Sleep,至少不会评论为什么他们已经投票了。

答案 4 :(得分:0)

This post对单元测试多线程应用程序进行了很好的讨论。

答案 5 :(得分:0)

你实际上不能。但是,您可以编写一些调试时代码(例程的开始,例程结束,特殊操作例程,......)写入控制台,这样您就可以看到这些例程同时运行。

答案 6 :(得分:0)

Thread.sleep代码。如果您遇到多线程的竞争条件,那么Thread.Sleep可以增加竞争条件的大小,使其更容易重现。

WriteA();
// potential race condition as another bit of code might read all the state
// and only get A in their read.
WriteB();

WriteA();
Thread.Sleep(60000);
WriteB();

然后您可以编写可以重现问题的代码。然后,您可以编写修复问题的代码。然后你可以声明你的修复工作。利润!

答案 7 :(得分:0)

另一个帖子使用Microsoft's CHESS程序发布了相关答案。