没有“ usleep()”或“ printf”,

时间:2018-10-31 03:25:48

标签: c++ c++11

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

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

if (!run) { break; }

通过循环中的“ usleep”或“ printf”之一,它可以很好地工作。

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

while (run)
{
     // Do something

     // usleep OR printf
}

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

谢谢, JL船长

2 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:1)

第一个猜测:“运行”变量未声明为易失性。