为什么多线程程序会陷入优化模式?
本文探讨了多线程程序中常见的问题,即程序陷入优化模式(- O1、-O2、-O3),但在未优化模式 (-O0) 下表现正常。
考虑以下用 C 编写的多线程程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static bool finished = false;
int func() {
size_t i = 0;
while (!finished)
++i;
return i;
}
int main() {
auto result = std::async(std::launch::async, func);
std::this_thread::sleep_for(std::chrono::seconds(1));
finished = true;
std::cout << "result =" << result.get();
std::cout << "\nmain thread>
|
登录后复制
在调试模式(未优化)或使用 GCC 的 -O0 标志运行此程序时,它通常会按预期运行并在 1 秒后打印结果。然而,当在发布模式或更高的优化级别(-O1、-O2、-O3)下编译时,程序会卡住并且不打印任何内容。
问题在于共享变量finished,即非原子且不受保护。优化编译器对内存访问指令重新排序,导致多个线程同时访问该变量,从而导致未定义的行为。要解决此问题,我们应该使用完成的原子变量。
这是更正后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # include <iostream>
# include <future>
# include <atomic>
static std::atomic<bool> finished = false;
int func() {
size_t i = 0;
while (!finished)
++i;
return i;
}
int main() {
auto result = std::async(std::launch::async, func);
std::this_thread::sleep_for(std::chrono::seconds(1));
finished = true;
std::cout << "result =" << result.get();
std::cout << "\nmain thread>
|
登录后复制
通过此修复,即使在优化模式下,程序也将正确运行。它演示了在多线程程序中使用原子变量来防止数据争用和未定义行为的重要性。
以上是为什么多线程程序在编译器优化下会冻结?的详细内容。更多信息请关注PHP中文网其他相关文章!