0

我正在尝试在 C++ 中模拟竞争条件。下面是我的代码,我使用 xcode 作为我的 IDE

相关代码如下:

int main(int argc, const char * argv[])
{
int value=0;
int* ptr = &value;

racer r1(ptr, "John");
racer r2(ptr, "Mike");

std::thread my_thread1(r1);
std::thread my_thread2(r2);

//guard g1(my_thread1);
//guard g2(my_thread2);

my_thread1.join();
my_thread2.join();

cout<<"result:= "<<*ptr<<endl;
cout <<"end!"<<endl;
return 0;

}

对于赛车手,我有:

racer::racer(int* r, char const* name)
{
    this->r=r;
    this->name=name;
}

void racer::print_result()
{
     cout<<this->name<<" "<<*r<<endl;
}

void racer::count_now()
{ 
    for ( int i = 0; i < 50; i++ )
    {
       *r = *r + 1;
       cout<<this->name<<". "<<*r<<endl;
    }
 }


void racer::operator()()
{
     count_now();
} 

所以基本上,没有比赛我的预期结果是 *ptr = 100 因为有 2 个线程在同一资源上一起运行。所以有时当我运行它时,我会得到 100,有时它会崩溃,我会收到下面的错误消息。这是为什么?换句话说,为什么我不能得到大于 100 的值?当它崩溃时是否意味着我有竞争条件并因此出现错误?

在此处输入图像描述

4

2 回答 2

1

您的示例代码不太可能产生竞争条件。竞争条件的前提是线程之间的上下文切换。你的例子太简单了

1) only two threads.
2) Each thread, on linux, by default, gets about 50ms CPU time for each context switch.

您的代码只有 50(增量 + cout)。这 50 个循环可以在 50 毫秒内轻松完成,因此两个线程在执行时无需任何上下文切换即可完成。如果没有(足够的)上下文切换,您将不会看到任何比赛条件。

为了提高您的机会:

1) start 50 threads.
2) each thread execute 50 loops.
3) each loop does 10 increments.

或者增加 1) 2) 3) 中的数字,直到您开始看到许多上下文切换并希望导致竞争条件。一个前兆是输出消息是混合的(“John”,“Mike”......)

于 2013-07-17T23:33:30.967 回答
1

首先是一个简单的问题:由于您使用 Xcode,我假设您使用基于 x86 的处理器。我的理解是,您将无法以您尝试的方式产生简单的数据竞争,因为基于 x86 的英特尔处理器实现了强大的缓存一致性协议,更准确地说是MESI 协议。在缓存一致性协议较弱的不同系统上,例如,在基于 ARM 的处理器上,我认为您会得到有趣的值,但目前我无法尝试。

更难的问题是:它为什么会崩溃?调试器清楚地显示了 IOStreams 库中的崩溃,这似乎是由于对std::cout. 但是,在调试器指向的行中,我真的看不出空指针取消引用的来源。唯一解引用的指针是is this(函数std::basic_streambuf<...>::overflow()virtual函数,即需要访问虚函数表)。

于 2013-07-17T21:41:03.483 回答