2012-08-05 17 views
3

在英特爾處理器手冊中:link的第8.2.3.4節中指出,可以將更早的存儲器重新排序到不同的位置,而不是將更早的存儲器重新排列到同一位置。內存重新排序:可以使用較早的商店將重新排序的內容重新排列到不同但包含的位置?

所以我理解,下面的兩個操作可以重新排序:

x = 1; 
y = z; 

與以下兩個操作不能重新排序:

x = 1; 
y = x; 

但會發生什麼,當存儲和負載適用於不同的地點,但負載完全包含商店,例如:

typedef union { 
    uint64_t shared_var; 
    uint32_t individual_var[2]; 
} my_union_t; 

my_union_t var; 
var.shared_var = 0; 

var.individual_var[1] = 1; 
int y = var.shared_var; 

所以在這種情況下'y'是0嗎?

編輯(@Hans Passant)爲了進一步解釋這種情況,我試圖看看我是否可以使用這種技術在不使用鎖定指令的情況下設計線程之間的準同步。

因此,一個更具體的問題,給定一個全局變量:

my_union_t var; 
var.shared_var = 0; 

而且兩個線程執行以下代碼:

主題1:

var.individual_var[0] = 1; 
int y = __builtin_popcountl(var.shared_var); 

線程2:

var.individual_var[1] = 1; 
int y = __builtin_popcountl(var.shared_var); 

兩個線程都可以'1'嗎?

注意:__builtin_popcountl是用於計算變量中設置的位數的內置gcc。

+0

排序只在多個內核訪問內存位置時起作用。從代碼片段中看不到,發佈的代碼永遠不會失敗。讓多個線程在沒有同步的情況下讀寫相同的內存位置並沒有實際用處。 – 2012-08-05 17:27:40

+2

考慮到C的一致性和排序問題,由於編譯器本身可能進行編號和優化,使事情變得複雜。例如,你的兩個線程的例子將會被破壞,因爲你沒有告訴編譯器union是volatile的。 – srking 2012-08-06 15:21:04

回答

0

CPU不知道或不在意你已經別名存儲位置。因此,你的第一個問題的答案是「不」。

您的第二個示例中的寫入操作不同步,因此,線程有可能擁有自己的數據副本。

對於您沒有問的問題(「我應該實現並使用自定義同步原語嗎?」)的答案是「否」。