所以我在SO和其他地方閱讀了大量關於共享變量,多線程和易失性主題的文章。基本類型的多線程和運算符++
如果考慮下面的代碼:
class C {
int x;
public:
C() : x(0) { }
void Operation() {
AcquireMutex();
++x;
ReleaseMutex();
}
};
現在,如果我已經明白了一切,到目前爲止我讀過,這將是更新x
以正確的方式,正確的?一個正確的編譯器不會對代碼重新排序,在調用AcquireMutex()
之前緩存x
的值,對吧?
我一直有一個習慣,用volatile
來標記這樣的變量。恐龍在地上漫遊時,我回到學校的東西,從來沒有真正反映過它。在主題閱讀文章後,又好像我已經浪費了我生命中的打字了幾分鐘(對於這些類型的用途)無用的關鍵詞......
UPDATE: 好了,如果我改變Operation()
此相反:
void Operation() {
AcquireMutex();
++x;
ReleaseMutex();
AcquireMutex();
++x;
ReleaseMutex();
}
現在,讓我們忽略了使用互斥的,並且內部函數如InterlockedIncrement(),或什麼的。除了我的觀點之外,這種說法還不錯
如果x
是不是標記爲volatile
,請問上面的代碼是線程安全的嗎?難道編譯器決定在第一次遞增之後將x
的最後一個值保存在一個寄存器中,然後只增加寄存器的值,並將其存儲在內存中的最後一個增量處?如果是這種情況,那麼上面的代碼不是線程安全的。是什麼賦予了?編譯器是否會假定在調用任何函數之後,所有緩存的變量都被認爲是「髒的」,從而迫使編譯器發出讀取操作?
嘗試在這種情況下使用互鎖操作,至少嘗試使用CRITICAL_SECTION,因爲它比Windows上的互斥量輕。可以設計跨平臺代碼[tbb :: atomic](http://threadingbuildingblocks.org/files/documentation/a00117.html)。 –