在Java中单元测试线程安全有什么令人满意的方法吗?

2022-09-01 00:07:57

我正在考虑改进一个包,我认为它在多个工作线程之间共享输入时不是线程安全的。根据TDD原则,我应该编写一些首先失败的测试,这些测试肯定会对评估问题有所帮助。

我意识到这不是一件简单的事情,而且天真的多线程测试将是非确定性的,因为操作系统将确定调度和各种操作交错的确切顺序。我过去看过并使用过多线程TC,这很有用。但是,在这种情况下,我事先确切地知道现有实现在哪里下降,因此能够编写一组很好的测试来涵盖它。

但是,如果您还没有确切地知道问题所在,那么是否有一种好方法可以编写一个很有可能抛出任何潜在问题的测试?有没有其他人认为有用的库?我认为从纯粹主义的角度来看,多线程测试用例应该与通常的单线程测试具有相同的调用和断言,并且仅在适当的情况下使用多个工作线程运行,我的想法是否正确?

欢迎就一般的工具/最佳做法/理念提出任何建议。


答案 1

Java 并发实践中有一些关于如何为并发问题编写测试的很好的信息。但是,它们不是真正的单元测试。几乎不可能为并发问题编写真正的单元测试。

基本上可以归结为这一点。创建一堆测试线程并启动它们。每个线程应

  • 等待倒计时闩锁
  • 反复调用一些修改所讨论的可变状态的方法
  • 第二个闩锁倒计时并退出

junit 线程创建所有线程并启动它们,然后在第一个闩锁上倒计时一次以让它们全部离开,然后等待第二个闩锁,然后对可变状态做出一些断言。

与其他类型的 Bug 相比,在发现 Bug ,为并发 Bug 编写失败的单元测试更容易。


答案 2

忘记通过测试并发问题来获得良好的结果。尝试减少同步并使问题变小。然后使用尽可能高的库支持来执行同步。只有当你真的有,然后尝试自己处理并发。当你知道每个工作线程都正确地完成它的工作,并且你所有的想法都告诉你,你有并发问题被舔,然后产生一些有趣的负载。Unittest框架及其扩展可以完成这项工作,但要知道您不再测试任何单元。(请记住,您已经覆盖了该部分)

如果您的并发模型变得复杂,请查看适合SPIN之类的工具。