2014-03-01 55 views
3

如果存在指針「A」和「B」,並且要求在對「B」的任何寫入變爲可見之前,應該使對「A」的任何寫入都可見。如果我不被允許使用鎖定,並且如果我不被允許將這些變量聲明爲「volatile」,下面的代碼是否能保證滿足上述要求?強制內存訂購

volatile temp; 

*A = value1; 
temp = *A; 

if (temp == value1) { 
    *B = value2 
} 
+1

* visible *表示什麼? –

+0

可能對其他線程可見。 – Codo

+0

我不認爲這個代碼會起作用。坦率地說,我不認爲讓A和B'volatile'也會有幫助。你需要某種內存屏障,(因爲這是C,而不是Java或C#)'volatile'與內存障礙無關。 – delnan

回答

2

答案很簡單。你不能。重新排序可能發生,因爲:

  • 編譯器將決定重新排序(雖然這取決於編譯器標誌等,但可以這樣做)。
  • 處理器將決定重新排序。如果處理器足夠複雜,它肯定會這樣做。

要強制記憶順序,您需要同步。不幸的是,這裏有很多方法。每種方法都有其優點和缺點。根據你的情況,你需要選擇一些。

0

不,它不會。而且你也無法用易變和簡單的C結構來實現它。編譯器可以自由地對代碼重新排序,只要你的程序工作正常(和其他人被定罪!)

所以問題是:你可以調用什麼其他選項?例如,如果唯一的要求是另一個任務從不會看到更新失序,則可以通過在設置A和B之間進行任何系統調用來有效保證。即使對位於遠處的存儲器位置的庫函數的調用可能也會執行工作。你真正需要做的就是超越最長的管道。但這可能需要一段時間...

這使我想到了這個問題:你將如何測試這個?以及時間至關重要?

可能需要更多信息才能真正回答問題。

1

我覺得這是完全合法的C編譯器重新安排您的示例代碼:

volatile temp; 

old_b = *B; 
*B = value2;  
*A = value1; 
temp = *A; 

if (temp != value1) { 
    *B = old_b; 
} 

類似的東西可能會更好:

volatile temp; 

temp = value1; 
*A = temp; 
temp = value2; 
*B = temp; 

但是,即使你知道B的存儲指令出現在A的存儲指令之後,這仍然不能保證其他線程按該順序「查看」修改。這將取決於緩存同步,並且基本上是不可預測的。您需要內存屏障或鎖定機制才能使其可靠工作。