2017-07-08 44 views
0

我一直在閱讀內存重新排序最近。我的問題是關於多線程場景。考慮下面的例子:內存訂購,超出其他執行和多線程安全

A = 0; 
B = 0; 

Thread 1 on Processor 1      Thread 2 on Processor 2 

    A = 100;          while(B== 0); 
    B = 1;          //access A here 

我一直在編碼上X86-64 Windows平臺上,從來沒有認爲商店A和B可以被重新排序(無論是在編譯器級或硬件級),我最終可能線程2中的B = 0,並且發現A仍然是0.並且從來沒有遇到任何問題或者使用這樣的代碼討厭的bug。這是因爲x86-x64的強烈排序,windows C編譯器也是如此。

對於這樣的代碼,要在任何其他弱平臺內存平臺上執行,是否需要確保我更新並訪問鎖內的A和B(假設底層鎖實現使用內存屏障並使鎖定爲鎖只有在所有處理器內核都可見之前的所有加載和存儲之後纔會被釋放)。

感謝

回答

1

是因爲x86的64位被強有序等等都是窗口的C編譯器。

確實,X86是一個強烈訂購的CPU,不允許存儲重新排序。所以所有的CPU核心都會觀察編譯器發出的命令。

但是,B在處理器1上被修改,而在處理器2上被讀取。如果沒有同步(嘗試最大化編譯器優化,它可能會停止工作),C存儲器模型將不允許這樣做。

儘管可以使用鎖定來在內核之間進行同步,但由於您正在旋轉B,因此可能會出現問題。如果發生這種情況,處理器1無法更新該值。

一個正確的解決方案是使Batomic。這將保證所有級別的正確訂購。

+0

LMimsey您的意思是最大限度地優化可以使編譯器級別重新排序。我沒有得到「這在C內存模型中是不允許的」。當B = 1時,強有序的x86應該保證A = 100,這是上面例子的意圖。 – san216

+0

另外我的問題的下一部分,在內存有限的平臺上,我是否需要注意,我在鎖內更新A和B.在所有操作系統平臺上鎖定原語是否會在鎖定釋放邏輯內部插入內存障礙,因爲否則,甚至鎖定可能無法防範硬件存儲器訪問重新排序。 – san216

+0

對2個或更多線程的單個內存位置的讀/寫訪問違反了內存模型規則(又名數據競賽)。結果是未定義的行爲。例如,由於你的編譯器可能不希望在覈心2上更新'B',它可能會簡單地將它從循環中取出。循環將永遠不會退出。 – LWimsey