关于多线程时的竞争条件的问题



所以我正在通读一本书,在这一章中,他们给了我一个对我来说没有意义的问题

我假设用param x创建3个函数,简单地计算x*x;一个使用互斥,一个使用原子类型,还有一个两者都不使用。并创建3个全局变量来保存这些值。前两个功能将防止比赛条件,但第三个功能可能不会。

之后,我创建了N个线程,然后循环并告诉每个线程计算它的x函数(3个单独的循环,每个函数一个。所以我创建了3次N个线程(

现在这本书告诉我,使用函数1&2我应该总是得到正确的答案,但使用函数3我不会总是得到正确答案。然而,我总是能为所有人找到正确的答案。我想这是因为我只是在计算x*x,这就是它所做的一切。

例如,当N=3时,正确的值是0*0+1*1+2*2=5。

这就是原子函数:

void squareAtomic(atomic<int> x)
{
accumAtomic += x * x;
}

这就是我如何调用函数

thread threadsAtomic[N]
for (int i = 0; i < N; i++) //i will be the current thread that represents x
{
threadsAtomic[i] = thread(squareAtomic, i);
}
for (int i = 0; i < N; i++)
{
threadsAtomic[i].join();
}

这是有时应该创造比赛条件的功能:

void squareNormal(int x) 
{
accumNormal += x * x;
}

我这样称呼它:

thread threadsNormal[N];
for (int i = 0; i < N; i++) //i will be the current thread that represents x
{
threadsNormal[i] = thread(squareNormal, i);
}
for (int i = 0; i < N; i++)
{
threadsNormal[i].join();
}

这都是我自己的代码,所以我可能没有正确回答这个问题,在这种情况下,我道歉。

竞争条件(以及通常未定义的行为(的一个问题是,它们的存在并不能保证您的程序会错误地运行。相反,未定义的行为只会使您的程序根据C++语言规范的规则进行操作的保证失效。这可能会使未定义行为很难通过经验测试来检测。(每个多线程程序员最可怕的噩梦是在程序密集的三个月测试期间从未见过的错误,只在现场观众面前的大型舞台演示中以神秘崩溃的形式出现(

在这种情况下,racy程序的竞争条件是多个线程同时读取和写入accumNormal;特别是,如果线程A读取accumNormal的值,然后线程B将新值写入accumNormal,然后线程A将新值写到accumNormal,从而覆盖线程B的值,则可能会得到不正确的结果。

如果你想向自己证明竞争条件确实会导致不正确的结果,你应该编写一个程序,让多个线程长时间地敲击同一个共享变量。例如,您可能让一半的线程将变量增加100万次,而另一半则将变量减少100万次。然后(即,在连接所有线程之后(检查最终值是否为零(这是您期望的值(,如果不是,则再次运行测试,并在必要时让该测试整夜运行。(即使这样也可能不足以检测不正确的行为,例如,如果您在硬件上运行,增量和减量是以这种方式实现的,它们"恰好可以工作"(

相关内容

  • 没有找到相关文章

最新更新