1

プログラム全体の最適化が有効になっている場合、コンパイラは関数呼び出しの順序を変更できますか? (/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
4

0 に答える 0