C++中有關volatile關鍵字的作用--阻止編譯器將其變數優化快取到暫存器(和執行緒相關)(轉自百度)
阿新 • • 發佈:2019-02-01
就象大家更熟悉的const一樣,volatile是一個型別修飾符(type specifier)。
它是被設計用來修飾被不同執行緒訪問和修改的變數
。
如果沒有volatile,基本上會導致這樣的結果:要麼無法編寫多執行緒程式,要 麼編譯器失去大量優化的機會。
上面程式碼中Gadget::Wait的目的是每過一秒鐘去檢查一下flag成員變數,當flag被另一個執行緒設為true時,該函式才會返回。至少這是程式作者的意圖,然而,這個Wait函式是錯誤的。
假設編譯器發現Sleep(1000)是呼叫一個外部的庫函式,它不會改變成員變數 flag
,
那麼編譯器就可以斷定它可以把flag快取在暫存器中,
以後可以訪問該暫存器來代替訪問較慢的主機板上的記憶體。
這對於單執行緒程式碼
來說是一個很好的優化,但是在現在這種情況下,它破壞了程式的正確性:
當你呼叫了某個Gadget的Wait函式後,即使另一個執行緒呼叫了Wakeup,Wait還是 會一直迴圈下去。
這是因為flag的改變沒有反映到快取它的暫存器中去。編譯器的優化未免有點太……樂觀了。
在大多數情況下,把變數快取在暫存器中是一個非常有價值的優化方法,如果不用的話很可惜。
C和 C++給你提供了顯式禁用這種快取優化的機會。如果你宣告變數是使用了volatile修飾符,編譯器就不會把這個變數快取在暫存器裡——每次訪問都將去 存取變數在記憶體中的實際位置。