我正在尝试用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的值?什么时候崩溃是否意味着我有竞争条件,因此错误?
答案 0 :(得分:1)
首先是一个简单的问题:因为你使用Xcode我假设你使用的是基于x86的处理器。我的理解是,您将无法按照您尝试的方式生成简单的数据竞争,因为基于x86的Intel处理器实现了强大的缓存一致性协议,更准确地说是MESI protocol。在具有较弱缓存一致性协议的不同系统上,例如,在基于ARM的处理器上,我认为你会得到有趣的值,但目前我无法尝试。
更难的问题是:为什么会崩溃?调试器清楚地显示了IOStreams库中的崩溃,这似乎是由std::cout
的并发访问引起的。但是,在调试器指向的行中,我无法真正看到空指针取消引用的来源。唯一被解除引用的指针是this
(函数std::basic_streambuf<...>::overflow()
是virtual
函数,即需要访问虚函数表。)
答案 1 :(得分:1)
您的示例代码不太可能产生竞争条件。竞争条件的前提条件是线程之间的上下文切换。你的例子太简单了
1) only two threads.
2) Each thread, on linux, by default, gets about 50ms CPU time for each context switch.
您的代码只有50(增量+ cout)。这50个循环可以在50ms内轻松完成,因此两个线程将在执行时完成而无需任何上下文切换。如果没有(足够的)上下文切换,您将无法见证任何种族关系。
提高你的机会:
1) start 50 threads.
2) each thread execute 50 loops.
3) each loop does 10 increments.
或增加1)中的数字2)3)直到你开始看到许多上下文切换并希望导致竞争条件。一个前兆将是输出消息混合(“John”,“Mike”......)