為什麼多執行緒程式會陷入最佳化模式?
本文探討了多執行緒程式中常見的問題,即程式陷入最佳化模式(- O1、-O2、-O3),但在未最佳化模式 (-O0) 下表現正常。
考慮以下用C 編寫的多執行緒程式:
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,即非原子且不受保護。最佳化編譯器對記憶體存取指令重新排序,導致多個執行緒同時存取該變量,從而導致未定義的行為。要解決此問題,我們應該使用完成的原子變數。
這是修正後的程式碼:
#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中文網其他相關文章!