筆者入職百度時,二面面試官的讓我聊聊C++之中的volatile關鍵詞。volatile在Java和C++之中的差異可謂是天差地別,我只是簡單聊了聊Java之中的volatile,面試官對個人回答並不滿意。後續學習《C++ Prmier》時,對volatile的理解也是雲裏霧裏。入職百度以後,發現身邊的同窗時候對volatile也是誤會頗多。(果真是「面試造核彈,工做擰螺絲」)因此筆者花了一些時間,整理了這篇文章,但願各位C++程序員能完全釐清volatile。java
volatile這個單詞在英文之中的意思是:易變的,不穩定的的含義。因此顧名思義,一旦變量經過了volatile關鍵詞修飾以後,說明變量是易變的和不穩定的。而C++之中最大的誤會就是認爲volatile關鍵詞與併發編程有關,至於爲什麼會引發這樣的誤會呢?筆者以爲罪魁禍首多是下面的緣由:程序員
volatile影響最爲深遠的就是Java之中的功用,筆者第一次接觸這個關鍵詞也是在Java之中。(加上數目龐大的Java程序員~~)Java之中volatile的效果是:面試
JDK5引入concurrent包中atomic,JDK6將synchronized關鍵字的性能優化後。絕大多數場景,筆者都再也不推薦使用volatile這個關鍵字了。編程
早期的 MSVC之中 volatile 具備Release和Acquire語義,這我想給許多 C++程序猿形成了誤解。後續微軟將這個關鍵字作了一個切換:volatile:ms,用加 ms 的修飾來延續以前的語義。
緩存
其實上一節對volatile 的誤用作了討論。接下來筆者來帶你們看看,實際 volatile 關鍵字到底起到怎麼樣的做用。先看以下的代碼:性能優化
int n = 10; int main() { int a = n; int b = n; return 0; }
咱們將這段代碼轉換爲彙編代碼,筆者這裏使用的** gcc 版本爲5.4.0:
接下來,咱們將變量添加上 volatile**關鍵字,看看會出現什麼效果:多線程
int n = 10; int main() { volatile int a = n; volatile int b = n; return 0; }
從新編譯這部分代碼轉換爲彙編代碼,咱們來看看:
看到這部分彙編代碼,想必各位應該對 volatile關鍵詞的做用應該心中有數了。volatile至關於顯式的要求編譯器禁止對 volatile 變量進行優化,而且要求每一個變量賦值時,須要顯式從寄存器%eax拷貝。volatile 關鍵字在嵌入式編程之中會須要用到,在特定環境下,寄存器的變量可能會發生變化。volatile 因此聲明瞭寄存器部分的數據是『易變的』,須要防止編譯器優化變量,強制載入寄存器。併發
可是若是須要實現相似 Java 之中 volatile 的效果呢?能夠在代碼之中顯式插入內存屏障,讓 CPU 強制刷新寄存器的變量到內存之中。性能
int n = 10; int main() { volatile int a = n; asm volatile("" ::: "memory"); volatile int b = n; return 0; }
如今咱們再來看看編譯生成的彙編代碼:
由上述的彙編代碼咱們能夠看到,在添加了內存屏障以後,對變量的賦值操做須要顯式的內存之中取值。實際 Java 在實現 volatile 關鍵字時,也是經過上述語句來實現的。學習
volatile 關鍵字自己在 現代的C++和 Java 之中都再也不推薦使用了。在 C++之中有不少對 volatile 的誤用。但願這篇文章可以幫助你們解惑 volatile ,可以正確的進行使用。學有不精,若有謬誤,請多多指教~~~