到目前为止,我已经避免了测试多线程代码的噩梦,因为它似乎是一个太大的雷区。我想知道人们是如何测试依赖于线程的代码以获得成功执行的,或者人们是如何测试那些仅在两个线程以给定方式交互时才会出现的问题的?
对于今天的程序员来说,这似乎是一个非常关键的问题,恕我直言,将我们的知识集中在这个问题上是很有用的。
到目前为止,我已经避免了测试多线程代码的噩梦,因为它似乎是一个太大的雷区。我想知道人们是如何测试依赖于线程的代码以获得成功执行的,或者人们是如何测试那些仅在两个线程以给定方式交互时才会出现的问题的?
对于今天的程序员来说,这似乎是一个非常关键的问题,恕我直言,将我们的知识集中在这个问题上是很有用的。
当前回答
您可以使用EasyMock。使测试实例线程安全
其他回答
下面的文章提出了两种解决方案。包装一个信号量(CountDownLatch),并添加诸如从内部线程外部化数据之类的功能。实现此目的的另一种方法是使用线程池(请参阅兴趣点)。
喷头-高级同步对象
我用与处理任何单元测试相同的方式处理线程组件的单元测试,即使用反转控制和隔离框架。我在. net领域进行开发,开箱即用的线程(以及其他东西)很难(我可以说几乎不可能)完全隔离。
因此,我写的包装器看起来像这样(简化):
public interface IThread
{
void Start();
...
}
public class ThreadWrapper : IThread
{
private readonly Thread _thread;
public ThreadWrapper(ThreadStart threadStart)
{
_thread = new Thread(threadStart);
}
public Start()
{
_thread.Start();
}
}
public interface IThreadingManager
{
IThread CreateThread(ThreadStart threadStart);
}
public class ThreadingManager : IThreadingManager
{
public IThread CreateThread(ThreadStart threadStart)
{
return new ThreadWrapper(threadStart)
}
}
从那里,我可以很容易地将IThreadingManager注入到组件中,并使用所选的隔离框架使线程在测试期间的行为符合我的预期。
到目前为止,这对我来说工作得很好,我对线程池,系统中的东西使用相同的方法。环境,睡眠等等。
我最近发现了一个叫做Threadsafe的工具(用于Java)。它是一个静态分析工具,很像findbugs,但专门用于发现多线程问题。它不是测试的替代品,但我可以推荐它作为编写可靠的多线程Java的一部分。
它甚至可以捕捉到一些非常微妙的潜在问题,比如类包容、通过并发类访问不安全的对象以及在使用双重检查锁定范式时发现丢失的volatile修饰符。
如果您编写多线程Java,请尝试一下。
上周我花了大部分时间在大学图书馆学习并发代码的调试。核心问题是并发代码是不确定的。通常,学术调试可以分为三个阵营之一:
Event-trace/replay. This requires an event monitor and then reviewing the events that were sent. In a UT framework, this would involve manually sending the events as part of a test, and then doing post-mortem reviews. Scriptable. This is where you interact with the running code with a set of triggers. "On x > foo, baz()". This could be interpreted into a UT framework where you have a run-time system triggering a given test on a certain condition. Interactive. This obviously won't work in an automatic testing situation. ;)
现在,正如上面评论者所注意到的,您可以将并发系统设计成更确定的状态。然而,如果你做得不好,你就又回到了设计顺序系统的问题上。
我的建议是,专注于制定一个非常严格的设计协议,规定什么是线程,什么不是线程。如果你限制了你的接口,使元素之间的依赖最小化,那就容易多了。
祝你好运,继续解决这个问题。
(如果可能的话)不要使用线程,使用actor /活动对象。易于测试。