マルチスレッド プログラムが最適化モードでスタックするのはなぜですか?
この記事では、プログラムが最適化モードでスタックする、マルチスレッド プログラムでよく発生する問題について説明します (- 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) でコンパイルすると、プログラムはスタックし、何も出力されません。
問題は、共有変数の completed にあります。非原子的であり、保護されていません。最適化コンパイラはメモリ アクセス命令を並べ替えるため、複数のスレッドがこの変数に同時にアクセスし、未定義の動作が発生します。これを修正するには、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 中国語 Web サイトの他の関連記事を参照してください。