我想在竞争条件下测试某些Object的函数的线程安全性。为了测试这一点,我想同时从两个(或更多)不同的线程中调用一个函数。我该如何编写代码来确保函数调用同时发生或至少足够接近以达到预期效果?
答案 0 :(得分:1)
您能做的最好的事情就是认真检查代码,并检查所有可能出现问题的小迹象。如果存在竞争条件,则您应该能够编写最终触发该条件的代码。考虑:
#include <thread>
#include <assert.h>
int x = 0;
void foo()
{
while (true)
{
x = x + 1;
x = x - 1;
assert(x == 0);
}
}
int main()
{
std::thread t(foo);
std::thread t2(foo);
t.join();
t2.join();
}
在所有测试它的地方,它都会快速断言。然后,我可以添加关键部分,直到断言消失。
但是实际上,不能保证它会断言。但是我在大规模生产代码中反复使用了这种技术。可以肯定,您可能只需要花很长时间来敲击代码。
答案 1 :(得分:-1)
具有一个结构,该结构的场数组为零,长度可能为300-500 kB。然后在两个原子内存发出障碍之前(从主线程通过检查原子变量的值来确保未定义的行为区域已完成),然后从两个线程中复制另外两个结构(一个具有1s,另一个具有2s)。 >
这应该很有可能发生不确定的行为,也许您可以在其中看到混合的1、2s(甚至0?),以了解发生了什么。
但是当您删除所有控制内容(例如原子)时,新形状也可能是另一种未定义的行为,并且行为有所不同。
答案 2 :(得分:-1)
执行此操作的一种好方法是插入定时良好的sleep
调用。例如,您可以使用它来强制按您要测试的顺序组合事件(线程1执行某些操作,然后线程2执行某些操作,然后线程1执行其他操作)。缺点是您必须知道将sleep
调用放在何处。经过一会儿之后,您应该会开始感觉到它,但是一开始的一些良好直觉会有所帮助。
如果可以获取线程ID的句柄,则可以有条件地调用sleep
或从特定线程中遇到断点。
此外,我非常确定Visual Studio和(我认为)GDB允许您冻结一些线程和/或运行特定的线程。