你有两个线程,一个运行函数f1(),另一个运行f2()。 有时f1从未完成,尽管看到了f2的所有打印件。 解释这怎么可能发生并提供解决方案?
int _f2_finished = 0;
Void f1()
{
print(“f1 waiting “);
while (!_f2_finished) {usleep(50);}
print(“share of work”);
}
void f2()
{
Printf(“f2 doing some stuff”);
usleep(5*1000*1000);
Printf(“f2 signaling finished”);
_f2_finished = 1;
Printf(“f2 signaled finished”);
}
我试图解决它我无法理解为什么f1()仍然停留在while循环中尽管f2打印的所有消息意味着_f2_finished都是1退出while循环?
它是C语言和Windows平台。
答案 0 :(得分:2)
大多数线程模型指定访问一个线程中的对象是非法的,而另一个线程正在或可能正在修改它。它们确实提供了合法共享数据的方法,例如原子操作,互斥体等。
碰巧,在这种特殊情况下,您需要“内存可见性”保证。也就是说,确保在另一个线程中“很快”看到在一个线程中进行的更改。保证内存可见性需要禁用许多编译器优化(例如缓存寄存器中的变量值),因此只有在请求它时才能获得它。
在Windows上,您有很多选择。您可以使用CRITICAL_SECTION来保护共享值,也可以使用各种Interlocked
操作。
在所有已知的Windows平台上,使用volatile
在不需要原子性的情况下提供内存可见性的工作正常发生,并且在不久的将来这种情况不太可能发生变化。如果您不理解,请忽略它,只使用易于纠正并且难以像互斥锁一样出错的内容。 (因为如果你使用volatile
这样没有深刻的认识,迟早你会在它发生不可靠地工作,你的代码将在最糟糕的时候最可怕的方式失败的情况下使用。)