如何在C++中创建争用条件



我想在竞争条件下测试一些对象的线程安全性。为了测试这一点,我想从两个(或多个(不同的线程同时调用一个函数。如何编写代码来保证函数调用将同时发生或至少足够接近以达到预期的效果?

你能做的最好的事情就是重敲代码,并检查你可能得到的问题的所有小迹象。如果存在争用条件,您应该能够编写最终触发它的代码。考虑:

#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();
}

无论我在哪里测试它,它都很快断言。然后我可以添加关键部分,直到断言消失。

但事实上,不能保证它会断言。但是我已经在大规模生产代码中反复使用了这种技术。可以肯定的是,您可能只需要长时间敲打代码。

有一个结构,其数组字段为零,长度可能为 300-500 kB。然后从两个线程中,将另外两个结构(一个有 1 个,另一个有 2 个(复制到它,就在某个原子内存发出屏障之前(以确保未定义的行为区域已经完成,通过检查原子变量的值从主线程(。

这应该很有可能出现未定义的行为,也许您可以看到混合的 1、2(甚至 0?(知道它发生了。

但是,当您删除所有控件内容(例如原子学(时,新形状也可能是另一种未定义的行为并且行为不同。

执行此操作的一个好方法是插入适时的sleep调用。例如,您可以使用它按要测试的顺序强制事件组合(线程 1 执行某些操作,然后线程 2 执行某些操作,然后线程 1 执行其他操作(。缺点是您必须知道将sleep调用放在哪里。在这样做了一会儿之后,你应该开始感觉到它,但一些好的直觉在开始时会有所帮助。

如果可以获取线程 id 的句柄,则可以有条件地调用sleep或从特定线程命中断点。

另外,我很确定Visual Studio和(我认为(GDB允许您冻结某些线程和/或运行特定线程。

最新更新