2017-07-20 65 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]可以坐在一個CPU的寫緩衝,我們開始一個新的線程在不同的CPU,這可能不遵守初始化寫道。

我們是否需要內存圍欄進行初始化,以便能夠通過運行在不同的cpus上的後續發佈的線程來觀察?

回答

1

在執行線程構造函數之前父項中的操作與子項中運行的線程過程之間存在「發生前 - 之間」關係。特別是標準說(f是線程程序):

同步:構造函數的調用的完成與f副本的調用開始同步。

這部分被發現[thread.thread.constr]

+0

謝謝你的理由。我很難閱讀標準。我找到你的報價。通過「與...同步」,我想這意味着編譯器可能會在調用f副本之前插入fence以確保在調用f之前所有存儲都將被觀察到? –

+0

@OliverYoung:該標準沒有提及內存隔離,因爲並非所有的CPU架構都需要它們。該標準說明了編譯器需要確保副作用可見的地方,以及操作重疊的位置(創建競爭條件),編譯器負責使用任何CPU功能提供的指定行爲。 –

+0

我明白了。只要非常清楚,初始化部分就會同步/「發生之前」調用f的副本。這意味着沒有競爭條件,不需要同步操作,對吧? –