什么可能导致死锁或以其他方式导致此并发测试不一致失败?

时间:2010-09-30 14:47:16

标签: .net random concurrency heisenbug

我一直在摆弄CHESS,这似乎是一个非常有用的工具。然而,具有讽刺意味的是,我似乎在我的一种测试方法中处理了一个Heisenbug。运行此测试时CHESS报告的结果是不可预测的:

  • 有时候测试会通过
  • 有时候测试会失败,没有进一步的描述(简单地说:“测试失败”)
  • 有时测试会失败并附有复制*
  • 的说明
  • 有时候测试会显示“CHESS检测到死锁”

最初,我认为这种不一致必定是因为测试涉及使用Random个对象。一定是不同的种子价值产生了不同的结果,对吗?

所以我更新了测试以简单地运行一组预定义的种子值(0到10)。线程局部Random对象由锁中的共享Random生成的(伪)随机值播种。代码看起来基本上 完全,如下所示:

Screenshot of CHESS reporting a deadlock

更新:我在.NET 3.5上运行此功能,因为CHESS仅支持VS 2008.我想知道问题是否与this有关?)

据我所知,上面的代码实际上应该是非常确定的。由于使用已知种子(0到10之间)初始化sharedRandom,因此属于运行localRandom调用内的代码的每个线程的Parallel.For对象生成的值应该是一致的测试运行到下一个(哪个线程获取来自sharedRandom的哪个种子在运行之间可能不同,但在Parallel.For内的5个迭代中,相同的5个种子应该用于localRandom)。< / p>

这就是了解它的方式。但是根据CHESS的结果,我倾向于相信我必须遗漏一些东西。

  1. 上面的代码中是否存在死锁,我太傻了?
  2. 我是否应该在并发相关测试中使用Random类?
  3. 对于有使用CHESS经验的人:它是一个可靠的工具吗?它有时会产生误报吗?这实际上是一个很大的问题,好像事实证明这种情况很常见(测试结果不一致),那么我可能暂时不推迟使用CHESS。
  4. * ...我无法弄清楚如何使用 - 但这是一个单独的问题。

2 个答案:

答案 0 :(得分:1)

没有答案,我会试一试。对我而言,发布的代码片段如何失败并不明显,我怀疑真正的问题出现在评论中。

我没有CHESS的实践经验,但研究得很好,知道你不能依赖它来给你可重复的测试结果。揭示线程问题的方法是非常统计的,在线程中注入随机延迟。旨在重现那些受时间特别严重影响的线程问题,特别是竞争条件。

如果代码执行时间可预测,竞争条件很长时间都不会被检测到。当它罢工时,难以诊断。这方面的一个很好的例子是我听说的一个大型政府项目随着日志记录一直开启。因为关闭它将不再有效,没有记录信息就没有好的方法来诊断问题。

威胁CHESS作为诊断工具。如果它引发了一个标志,你可以相当确定你有一个真实但仍然很难解决的线程问题。

答案 1 :(得分:1)

我当然没有看到僵局。 Random可能有内部锁定,但这应该没问题。

您可能想尝试一下Jinx(www.corensic.com)。 Jinx不是生成报告,而是改变各种CPU的有效性能。所以它不能真正产生误报。

如果微小的样本在Jinx下死机,那么它在正常使用期间肯定能够解锁。假设它确实死锁,你应该能够使用Visual studio进入死锁并查看线程的位置。

声明。我为corensic工作。而且我认为你发布的小片段并没有真正的僵局。但我很好奇,所以让我们知道你发现了什么。