2013-07-17 79 views
0

我想在C++中模拟竞争条件。下面是我的代码,我使用了Xcode作为我的IDE竞争条件模拟崩溃在xcode

相关的代码是这样的:

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的值?当它崩溃是否意味着我有一个竞争条件,从而出现错误?

enter image description here

+0

代码在我的linux上工作正常。 – ROTOGG

+0

@Leon Li您是否得到了> 100的结果? – adhg

回答

1

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

更难的问题是:它为什么会崩溃?调试器清楚地显示IOStreams库中的崩溃,这似乎是由于同时访问std::cout而导致的。但是,在调试器指向的线上,我无法真正看到空指针取消引用的来源。解除引用的唯一指针是this(函数std::basic_streambuf<...>::overflow()是一个virtual函数,即需要访问虚函数表)。

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),直到你开始看到许多上下文切换,并希望导致竞争条件。一个前兆将是输出消息混合(“约翰”,“迈克”...)