2011-12-21 51 views
3

假設我們有一個多線程的C程序(pthreads),並且各個線程的(非同步)共享變量訪問不會被編譯器重新排序。 x86 CPU是否尊重共享變量訪問的順序(在單個線程中),還是有可能重新排序某些內存訪問?多線程和無序執行

+0

無序/推測調度執行只存在於微代碼級別(後端)。 (請通知@我,因爲我沒有手動檢查答案) – user2284570 2013-11-23 01:47:22

回答

0

非同步共享變量訪問是危險的,並且亂序是其原因之一。
x86保持寫入順序(在一個線程內),但不能讀取。

如果您認爲訂單仍然存在,這可能會讓您陷入困境。例如:
線程A寫入x然後寫入y。假設編譯器沒有對它重新排序,CPU不會重新排序(x86不會,其他可能)。
線程B讀取y,然後讀取x。你可能會認爲,如果它具有y的新價值,那麼你肯定也會得到x的新價值。
並非如此。 CPU可能會對線程B的讀取進行重新排序,所以y會被更早讀取。

編輯:爲「單向的男人」中指出,在這種情況下,X86保證排序(但不是所有的處理器!)。
我引用英特爾軟件開發人員手冊:

寫入由單個處理器中所有 處理器相同的順序觀察。

這對於多處理器寫入來說並不正確 - 它們看起來可能被不同的處理器按不同的順序排列。

但是,我強烈建議不要依賴它,並使用適當的同步來代替。
同步原語是通過原子操作和/或障礙來實現的,它們保證您的安全。

+0

您是否可以用另一次讀取重新排序讀取? 「線程B讀取y然後讀取x,您可能會認爲如果它獲得了y的新值,那麼您肯定也會得到x的新值。」我不認爲這是真實的根據英特爾手冊:「讀取不會與其他讀取重新排序」。閱讀可以重新排序與舊的寫作雖然。 – 2013-09-09 20:33:32

+0

@ManofOneWay,你說得對。該手冊還指出「所有處理器以相同順序觀察單個處理器寫入」。我認爲,我的底線是正確的 - 根據這些細節編寫正確的無同步代碼幾乎是不可能的。 – ugoren 2013-09-10 08:51:58

+0

x86在加載和舊存儲時不保證排序,因此如果存在A然後是加載B,並且它們引用不同的存儲位置,則加載B可能會在A之前移動。因此,隔離仍然存在在某些情況下需要。 – 2013-09-10 09:02:07