Multithreading 多线程两个线程到达同一点

Multithreading 多线程两个线程到达同一点,multithreading,Multithreading,您有两个线程,一个运行函数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”);

您有两个线程,一个运行函数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平台。

大多数线程模型都规定,在一个线程中访问对象是非法的,而另一个线程正在或可能正在修改它。它们确实提供了合法共享数据的方法,如原子操作、互斥等

碰巧,在这种特殊情况下,您需要“内存可见性”保证。也就是说,确保在一个线程中所做的更改“很快”会在另一个线程中看到。要保证内存的可见性,需要禁用许多编译器优化(例如在寄存器中缓存变量的值),因此只有在请求时才能得到它

在Windows上,您有很多选择。您可以使用关键部分来保护共享值,也可以使用各种
联锁操作


在所有已知的Windows平台上,在不需要原子性的情况下,使用
volatile
提供内存可视性,这种情况在不久的将来不太可能改变。如果你不明白这一点,就忽略它,只使用一些像互斥锁这样容易纠正、难出错的东西。(因为如果您在没有深入理解的情况下以这种方式使用
volatile
,迟早您会在它工作不可靠的情况下使用它,并且您的代码会在最坏的时间以最坏的方式失败。)

您使用的是什么线程库或线程模型?在一个线程中访问一个对象,而另一个线程正在或可能正在修改它,这说明了什么?我仍然不理解为什么在另一个线程修改对象时访问该对象是非法的。该值将被更新,f1将退出该线程loop@Nizarazo这是违法的,因为这是规定。不能保证“值迟早会更新”,因为没有“值”这样的东西。没有“一个真实值”,因为规则不要求存在。规则只是要求如果程序遵循规则,它就可以正常工作。它们不需要编译器来找出如何使违反规则的程序工作。在您的例子中,
while
循环可能只读取
\u f2\u finished
一次。因为规则说你不能在另一个线程中修改它,编译器可以自由地假设它的值不能改变。这使得遵循规则的代码更加高效。编译器不需要弄清楚如何使你的天真假设保持有效,而且很可能不是这样。这里还有一个非常有价值的小问题。永远不要因为你想不出一种失败的方法,就断定代码是安全可靠的。没有人聪明到能想到所有非平凡代码可能失败的方法。你需要保证代码是有效的。你是说在windows中有这样一条规则:“因为规则说你不能在其他线程中修改它”?