1.首先第一步应该是先代码审阅,在审阅多线程代码时,重点要检查与并发相关的错误。
审阅多线程代码需要考虑的问题:
这里,列一下我的清单:
并发访问时,那些数据需要保护?
如何确定访问数据受到了保护?是否会有多个线程同时访问这段代码?这个线程获取了哪个互斥量?其他线程可能获取哪些互斥量?两个线程间的操作是否有依赖关系?如何满足这种关系?这个线程加载的数据还是合法数据吗?数据是否被其他线程修改过?当假设其他线程可以对数据进行修改,这将意味着什么?并且,怎么确保这样的事情不会发生?可测试性设计
通常,如果代码满足一下几点,就很容易进行测试:
1.每个函数和类的关系都很清楚。2.函数短小精悍。3.测试用例可以完全控制被测试代码周边的环境。4.执行特定操作的代码应该集中测试,而非分布式测试。5.需要在完成编写后,考虑如何进行测试。最后一个因素尤为重要:即使不在写完代码后,去写测试用例,这也是一个很好的建议,能让你在写代码之前,想想应该怎么去测试它——用什么作为输入,什么情况看起来会让结果变得糟糕,以及如何激发代码中潜在的问题,等等。
并发代码测试的一种最好的方式:去并发化测试。如果代码在线程间的通讯路径上出现问,就可以让一个已通讯的单线程进行执行,这样会减小问题的难度。
例如,当应用设计为一个多线程状态机时,可以将其分为若干块。将每个逻辑状态分开,就能保证对于每个可能的输入事件、转换或其他操作的结果是正确的;这就是使用了单线程测试的技巧,测试用例提供的输入事件将来自于其他线程。之后,核心状态机和消息路由的代码,就能保证时间能以正确的顺序,正确的传递给可单独测试的线程上,不过对于多并发线程,需要为测试专门设计简单的逻辑状态。或者,如果将代码分割成多个块(比如:读共享数据/变换数据/更新共享数据),就能使用单线程来测试变换数据的部分。麻烦的多线程测试问题,转换成单线程测试读和更新共享数据,就会简单许多。
一件事需要小心,就是某些库会用其内部变量存储状态,当多线程使用同一库中的函数,这个状态就会被共享。这的确是一个问题,并且这个问题不会马上出现在访问共享数据的代码中。不过,随着你对这个库的熟悉,就会清楚这样的情况会在什么时候出现。之后,可以适当的加一些保护和同步,或使用B计划——让多线程安全并发访问的功能。
构建多线程测试代码
在特定时间内,你需要安排一系列线程,同时去执行指定的代码段。最简单的情况:两个线程的情况,就很容易扩展到多个线程。
首先,你需要知道每个测试的不同之处:1.环境布置代码,必须首先执行2.线程设置代码,需要在每个线程上执行3.线程上执行的代码,需要有并发性4.在并发执行结束后,后续代码需要对代码的状态进行断言检查最终,我们还了解了一些对测试很有帮助的工具。
以上摘抄自《C++并发编程实战》比如说:
1.Visual Studio提供了“线程”窗口、“GPU 线程”窗口、“并行监视”窗口和其他可简化多线程调试的功能。
2.Thread Checker,Thread Profiler,能以较直观的方式发现问题。