思维导图:
引言:
本文的主要内容是介绍如何测试并发程序。因为全是都只是对并发程序的测试的简要描述,所以基本上都归属于理论部分。
- 理论部分:包括正确性测试,性能测试,和其他测试
一.正确性测试
对于并发程序来说,我们应该首先保证其正确性,即能够正确运行并获得正确的结果。那么,如何保证并发程序的正确性呢?我们可以从需要检查的不变性条件和后验条件入手,并从以下几个方面进行分析。
- 串行逻辑测试:在单线程的环境下进行测试,保证代码的基本运行良好。
- 阻塞测试:某些操作可能会涉及到阻塞,我们可以创建一个可以使并发程序阻塞的线程,然后观察其是否阻塞的结果。
- 安全性测试:统计出需要进行检查的不变性条件和后验条件,然后通过一个校验函授或其他方式进行校验。
- 资源管理测试:使用商业的或者开源的堆分析工具,检验并发程序是否不合理的使用了内存。
- 回调测试:在对象已知的某个生命周期判断其不变性条件是否被破坏。
- 交替性测试:很多错误都是在线程交替时出现的,所以,我们可以产生更多的线程交替操作以进行这种测试。
二.性能测试
在保证了程序的正确性后,我们就可以对程序的性能进行测试了。性能测试的目标就是根据测试的结果调整各种不同的限值,以使并发程序获得最好的性能。
2.1 性能测试的方式
我们可以通过以下几种方式对性能进行测试和衡量:
- 添加计时功能:通过对并发程序添加计时功能已衡量其性能
- 多种算法比较:同时对比使用多种算法的耗时结果以选择最好的实现算法
- 响应性衡量:通过统计每个线程的完成时间以衡量并发程序的吞吐量和响应性
2.2 性能测试的陷阱
进行性能测试有一些常见的陷阱,如下所示:
- 垃圾回收:因为垃圾回收无法预测,并会对测试结果造成影响,所以在测试期间,要么没有垃圾回收,要么执行多次回收。
- 动态编译:当某个方法运行的次数足够多时,JVM会将字节码直接编译为机器码以提高运行速度,这个时机是不可空的,并且会对测试结果造成显著的影响。为了避免这个情况,我们可以在运行几分钟后进行性能测试。
- 对代码路径的不真实采样:JVM会通过执行过程中特定的信息来优化代码,所以,同一个方法,在不同的程序中的编译结果可能是不同的。所以,测试时,我们需要尽量覆盖我们需要执行的代码路径,并且将单线程和多线程的性能测试结果在一起。
- 不真实的竞争程度:要获得有实际意义的测试结果,就需要模拟最接近正式环境的并发量和竞争程度。
- 无用代码的消除:JVM编译时会自动消除某些不会对输出结果产生任何影响的代码。由于基准测试通常不会执行任何运算,所以很容易被编译器消除,我们可以通过打印某些信息或者其他方式以防止基准测试的代码被消除。
三.其他的测试方法
还有一些其他的方法帮我我们找出并发程序可能出现的错误,简要如下所示:
- 代码审查:通过多人对代码进行代码审查,可以最大限度的发现安全性性错误和其他错误。
- 静态分析工具:利用一些静态的代码分析工具,在编译期之前就发现可能出现的问题。
- 面向切面技术:利用面向切面技术保证不变性条件不被破坏。
- 分析与检测工具:利用商业分析工具对并发程序进行分析和鉴定。