1

物理シミュレーション用のプログラムを作成しようとしています。1 つは計算用、もう 1 つは GUI 用の 2 つのスレッドを使用します。それらの間でデータを交換するには、構造体を使用します

struct sim_data {  
     int running;  
     int steps;  
    int progress;  
 ...  
};

それを別のスレッドに含めます

void *sim(void *args) {  
    struct sim_data *my_data;  
    my_data=(struct sim_data *)args;  
    ...  
}

で値を設定する場合

my_data->progress=1000;

データは同じスレッドで利用できますが、2 番目のスレッドでは確実ではありません。プログラムを開始して2番目のスレッドで別の値を読み取り、最初のスレッドに書き込む場合、10%の可能性があると思います。データはループで書き込まれますが、タイミングの問題ではないと思います。

これはとても奇妙だと思います。何がうまくいかないと思いますか?

4

2 に答える 2

1

C++11 仕様では、あるスレッドがある場所に書き込みを行い、2 番目のスレッドが同じ場所に読み書きできる場合はいつでも、データ競合ケースが発生すると宣言しています。これが発生すると、未定義の動作が発生することが宣言されています。あなたの場合、あるスレッドが my_data->progress に書き込み、別のスレッドがそれを読み取っています。

解決策は、アトミック int やロックなどの同期を使用することです。

C++ コンパイラは、シングル スレッド プログラムの実行を高速化するために非常に優れた最適化を行います。たとえば、シングル スレッドの世界では、1000 の値を確認する方法がなく、単純に出力しないことを選択することが証明される場合があります。

合法であるさらに醜いケースがあります。1000 を格納する必要があることをコンパイラが認識している場合、コンパイラは何も格納しないことを選択し、最終的に 1000 を格納する前に、より多くのスペースを割り当てるのではなく、そのメモリを一時的な結果を「こぼす」スペースとして使用する可能性があります。その間、任意の値を読み取ることができます。

この問題に関するかなりユーモラスな見解: http://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-c​​ould-possibly-go-wrong

于 2013-09-01T05:25:28.837 に答える