如果存在指針「A」和「B」,並且要求在對「B」的任何寫入變爲可見之前,應該使對「A」的任何寫入都可見。如果我不被允許使用鎖定,並且如果我不被允許將這些變量聲明爲「volatile」,下面的代碼是否能保證滿足上述要求?強制內存訂購
volatile temp;
*A = value1;
temp = *A;
if (temp == value1) {
*B = value2
}
如果存在指針「A」和「B」,並且要求在對「B」的任何寫入變爲可見之前,應該使對「A」的任何寫入都可見。如果我不被允許使用鎖定,並且如果我不被允許將這些變量聲明爲「volatile」,下面的代碼是否能保證滿足上述要求?強制內存訂購
volatile temp;
*A = value1;
temp = *A;
if (temp == value1) {
*B = value2
}
您將要使用的內存屏障或柵欄:看http://en.wikipedia.org/wiki/Memory_barrier
在Linux內核中,你可以使用rmb()
或wmb()
電話。
根據pthreads
您可以使用pthread_barrier_wait()
,雖然這似乎不在我的pthreads手冊頁中。
在MSVC上,看看Force order of execution of C statements?--它也有一些很好的一般信息。
如果您找到一個「原子」庫,通常會包含屏障功能。
答案很簡單。你不能。重新排序可能發生,因爲:
要強制記憶順序,您需要同步。不幸的是,這裏有很多方法。每種方法都有其優點和缺點。根據你的情況,你需要選擇一些。
不,它不會。而且你也無法用易變和簡單的C結構來實現它。編譯器可以自由地對代碼重新排序,只要你的程序工作正常(和其他人被定罪!)
所以問題是:你可以調用什麼其他選項?例如,如果唯一的要求是另一個任務從不會看到更新失序,則可以通過在設置A和B之間進行任何系統調用來有效保證。即使對位於遠處的存儲器位置的庫函數的調用可能也會執行工作。你真正需要做的就是超越最長的管道。但這可能需要一段時間...
這使我想到了這個問題:你將如何測試這個?以及時間至關重要?
可能需要更多信息才能真正回答問題。
我覺得這是完全合法的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的存儲指令之後,這仍然不能保證其他線程按該順序「查看」修改。這將取決於緩存同步,並且基本上是不可預測的。您需要內存屏障或鎖定機制才能使其可靠工作。
* visible *表示什麼? –
可能對其他線程可見。 – Codo
我不認爲這個代碼會起作用。坦率地說,我不認爲讓A和B'volatile'也會有幫助。你需要某種內存屏障,(因爲這是C,而不是Java或C#)'volatile'與內存障礙無關。 – delnan