2017-07-20 7 views
0

C++の初期化処理のメモリセマンティクスは不明です。 次のプログラムがあるとします。マルチスレッド環境での初期化のメモリセマンティクス(C++)

#include <iostream> 
#include <thread> 

using namespace std; 

void func(int* arr, int s) 
{ 
    for (int i = 0; i < s; ++i) 
    { 
     cout << arr[i] << endl; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    int *a = new int[10]; 
    for (int i = 0; i < 10; ++i) 
    { 
     a[i] = i; 
    } 

    // Do I need some sort of memory barrier here? 
    std::thread t(func, a, 10); 
    t.join(); 
    return 0; 
} 

新しいスレッドは、適切に初期化された配列を参照しますか?または、挿入の間に何らかの種類のメモリバリアが必要ですか? C++言語はどのように初期化のメモリセマンティクスを定義しますか?

私の懸念は、配列[10]へのすべての書き込みが1つのCPUの書き込みバッファにある可能性があり、初期化の書き込みを観察しない可能性がある別のCPUで新しいスレッドを開始することです。

異なるCPU上で実行されている後で発行されるスレッドで初期化するためにメモリフェンスが必要ですか?

答えて

1

スレッドコンストラクタを実行する前に親の操作と子で実行されているスレッドプロシージャとの間には、「発生前」の関係があります。特に標準(fスレッドプロシージャである)と言う:

同期:コンストラクタの呼び出しの完了は、fのコピーの呼び出しの開始と同期させます。

これは、セクションの引用のための[thread.thread.constr]

+0

感謝を発見されました。私は標準を読むのに苦労しました。私はあなたの引用符を見つけた。 「同期する」とは、コンパイラがfのコピーを呼び出す前にフェンスを挿入して、fを呼び出す前にすべてのストアを確認することを意味します。 –

+0

@OliverYoung:標準ではメモリフェンスについて何も言及していません。なぜなら、すべてのCPUアーキテクチャがそれらを必要とするわけではないからです。コンパイラは、副作用が見えるようにする必要がある場所と、オペレーションが重複する(競合条件を作成する)場所を示し、コンパイラは、指定された動作を与えるCPU機能を使用します。 –

+0

私は参照してください。非常に明確にするために、初期化部分はfのコピーの呼び出しを "起こる前に"同期します。つまり、競合状態はなく、同期操作は必要ありません。 –

関連する問題