プログラム全体の最適化が有効になっている場合、コンパイラは関数呼び出しの順序を変更できますか? (/GLスイッチ)
マルチスレッド環境でコードを壊すことはありませんか?
次の擬似コードを検討してください。
Thread1
{
numbers.append( 1 );
numbers.append( 2 );
numbers.append( 3 );
numbers.append( 1 );
numbers.append( 2 );
numbers.append( 3 );
manager.signalFinished();
}
Thread2
{
// is the compiler allowed to reorder the next two lines?
bool isReady = manager.isFinished();
int lastElem = numbers.getLastElement();
if( 3 == lastElem )
{
if( isReady )
{
TerminateThread();
}
else
{
// go back to start
continue;
}
}
}
合計 2 つのスレッドがあります。
スレッド 1 は番号をリストに入れ、終了すると、すべての番号がリストにあるというシグナルをトリガーします。完全なリストの場合、最後の要素は常に でなければならないと仮定します3
。
スレッド 2 は、シグナルが設定されているかどうか、および最後の要素が であるかどうかを確認し3
ます。
すべての関数が異なるコンパイル単位にあると仮定すると、プログラムは問題なく実行されるはずです。
プログラム全体の最適化により、コンパイラが関数呼び出しを並べ替える (またはそれらを並列に実行する) ことができるようになると、このプログラムは壊れる可能性があります。スレッド 2 の最初の 2 行は、コンパイラとは関係がないように見えますが (ミューテックスを共有していません)、実際には深いレベルで論理的にリンクされています。
並べ替えにより、次のような状況が発生する可能性があります。
Thread1: numbers.append( 1 );
numbers.append( 2 );
numbers.append( 3 );
Thread2: int lastElem = numbers.getLastElement(); // is 3
Thread1: numbers.append( 1 );
numbers.append( 2 );
numbers.append( 3 );
manager.signalFinished();
Thread2: bool isReady = manager.isFinished(); // is true
// now TerminateThread would be invoked
// and the second 1, 2, 3 of Thread1 would be lost