我很好奇,是否有人知道为什么没有“ usleep”或“ printf”的情况下,c ++中的简单while循环不会终止?

我有一个布尔值,其值从外部更改,其值旨在终止while循环。
我也尝试过,但失败了:

if (!run) { break; }


与循环中的“ usleep”或“ printf”之一配合使用,效果很好。

我有一种直觉,这与打断有关,但不确定为什么。

while (run)
{
     // Do something

     // usleep OR printf
}


虽然我可以轻松地执行“ usleep(0)”并且它可以工作,但我对为什么会这样很好感到好奇。
我的系统是运行C ++ 11(GCC / G ++ 5.4)的Ubuntu 16.04。

谢谢,
上尉

最佳答案

官方的答案是:如果要在线程之间共享一个(非原子的)布尔变量,并且不序列化对该变量的访问(例如,使用互斥锁),那么您将调用未定义的行为,并且程序可以自由地执行任何操作喜欢(按预期方式工作,以其他方式工作,崩溃,从钱包中窃取现金等)。

更为实际的答案是:在现代多核计算机上,每个核都有自己的寄存器和单独的L1缓存,因此,如果在核1上运行的线程设置了特定的内存位置,那么在核2上运行的另一个线程可能不会除非编译器已采取特定步骤以确保更改在内核之间传播,否则“查看”该更改。此外,除非您(程序员)已采取显式措施让编译器知道某个特定变量将被多个线程使用,否则编译器的优化器可能会假定该变量不能在给定线程的执行流程之外进行更改,并因此可能会完全删除对变量状态的测试(因为毕竟,如果编译器“证明”了变量值无法更改,为什么要浪费CPU周期检查其状态?)。

在您的情况下,可能发生的情况是,对printf()usleep()的调用具有副作用(例如,usermode-> kernel-> usermode开关),其中包括刷新内核的缓存,以便第二个线程(至少最终) “看到”第一个线程所做的更改-尽管没有这些调用,但没有理由同步缓存,因此永远不会“看到”更新。

实用建议:如果要在线程之间共享变量,请确保使用std::atomic<bool>而不是普通的bool,或者在内部序列化/保护对该变量的所有访问(读取和写入)互斥或关键部分。否则,您可能会遇到很多这种“有趣”的行为。

关于c++ - 没有“usleep()”或“printf”,while循环不会终止,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53075827/

10-11 18:14