空循环而不循环检查条件

时间:2010-08-17 18:40:44

标签: c++ multithreading sleep conditional-statements while-loop

在多线程C ++程序中,我在一个线程中运行了相同的操作:

while(obj->member) { } // waiting for obj->member to be set to false in another thread

在另一个帖子中,obj-> member设置为false。但是,即使将其设置为false,循环也不会中断。如果我改成它:

while(obj->member) { Sleep(1) }

当obj-> member在另一个帖子中设置为false时,它按预期工作并中断 为什么它会像这样工作?

5 个答案:

答案 0 :(得分:10)

尝试制作成员volatile。这将强制每次使用它时从内存中取出它,而不是从CPU寄存器中取出(这是编译器可能优化它的方式。)

答案 1 :(得分:6)

Obj必须声明为volatile。这告诉编译器它的值可能会被其他一些线程改变。

当您添加Sleep时,编译器知道其他线程正在运行,并假设它可能会更改。

答案 2 :(得分:4)

它的工作原理大多是偶然的。如果你想要可靠地做这样的事情,你只需要使用某种OS提供的IPC机制,可能使用Boost Interprocess(例如,互斥或信号量)来提供更便携的前端。

volatile虽然经常被提出作为这样的问题的解决方案,但既不必要也不充分。它可能会损害性能(很多),但仍然不足以使线程正常工作。如果您正在为.NET编程,Microsoft 定义其版本volatile以提供(至少某种程度的)线程安全性。否则(在真正的C或C ++中),它几乎没有用,并且会造成相当大的伤害。

我还应该提到,从第一次犯这个错误开始,这是 long 方式。回想起当时,Andre Alexandrescu在Dobbs医生中写了一篇关于使用volatile进行线程化的相当实质性的文章。他已经意识到他错了,但(在很大程度上)损害已经完成 - 特别是因为volatile非常接近于做正确的事情,因此很容易将其误认为正确/有用在线程中。

答案 3 :(得分:2)

更好的方法是使用事件而不是bool。通过一个事件,您可以在不使用任何CPU的情况下等待,而且您不必睡觉或使用volitile。

答案 4 :(得分:0)

也许你的线程库在创建线程时正在创建对象的副本,并且除非被声明为静态,否则成员之间不会真正共享成员。