volatile型別修飾符的使用

2021-08-30 03:58:25 字數 1399 閱讀 5222

儘管c和c++標準對於執行緒都明顯的「保持沉默」,但它們以volatile關鍵字的形式,確實為多執行緒保留了一點特權。

就象大家更熟悉的const一樣,volatile是乙個型別修飾符(type modifier)。它是被設計用來修飾被不同執行緒訪問和修改的變數。如果沒有volatile,基本上會導致這樣的結果:要麼無法編寫多執行緒程式,要麼編譯器失去大量優化的機會。下面我們來乙個個說明。

考慮下面的**:

class gadget

}

void wakeup()

...

private:

bool flag_;

};

上面**中gadget::wait的目的是每過一秒鐘去檢查一下flag_成員變數,當flag_被另乙個執行緒設為true時,該函式才會返回。至少這是程式作者的意圖,然而,這個wait函式是錯誤的。

假設編譯器發現sleep(1000)是呼叫乙個外部的庫函式,它不會改變成員變數flag_,那麼編譯器就可以斷定它可以把flag_快取在暫存器中,以後可以訪問該暫存器來代替訪問較慢的主機板上的記憶體。這對於單執行緒**來說是乙個很好的優化,但是在現在這種情況下,它破壞了程式的正確性:當你呼叫了某個gadget的wait函式後,即使另乙個執行緒呼叫了wakeup,wait還是會一直迴圈下去。這是因為flag_的改變沒有反映到快取它的暫存器中去。編譯器的優化未免有點太……樂觀了。

在大多數情況下,把變數快取在暫存器中是乙個非常有價值的優化方法,如果不用的話很可惜。c和c++給你提供了顯式禁用這種快取優化的機會。如果你宣告變數是使用了volatile修飾符,編譯器就不會把這個變數快取在暫存器裡——每次訪問都將去訪問變數在記憶體中的實際位置。這樣你要對gadget的 wait/wakeup做的修改就是給flag_加上正確的修飾:

class   gadget    

;

大多數關於volatile的原理和用法的解釋就到此為止,並且建議你用volatile修飾在多個執行緒中使用的原生型別變數。然而,你可以用volatile做更多的事,因為它是神奇的c++型別系統的一部分。

把volatile用於自定義型別

volatile修飾不僅可以用於原生型別,也可以用於自定義型別。這時候,volatile修飾方式類似於const(你也可以對乙個型別同時使用const和volatile)。

與const不同,volatile的作用對於原生型別和自定義型別是有區別的。就是說,原生型別有volatile修飾時,仍然支援它們的各種操作(加、乘、賦值等等),然而對於class來說,就不是這樣。舉例來說,你可以把乙個非volatile的int的值賦給乙個volatile的int,但是你不能把乙個非volatile的物件賦給乙個volatile物件。

volatile型別修飾符的作用

volatile關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改,比如 作業系統 硬體或者其它執行緒等。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的 就不再進行優化,從而可以提供對特殊位址的穩定訪問。使用該關鍵字的例子如下 int volatile nvint 當要求使...

關於volatile修飾符

volatile是乙個型別修飾符 type specifier 它是被設計用來修飾被不同執行緒訪問和修改的變數。如果沒有volatile,基本上會導致這樣的結果 要麼無法編寫多執行緒程式,要麼使編譯器失去大量優化的機會。乙個定義為volatile的變數是說 這變數可能會被意想不到地改變 這種意外不是...

型別修飾符volatile關鍵字

volatile關鍵字是一種型別修飾符,用它宣告的型別變數表示可以被某些編譯器未知的因素更改,比如 作業系統 硬體或者其它執行緒等。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的 就不再進行優化,從而可以提供對特殊位址的穩定訪問。使用該關鍵字的例子如下 int volatile nvint 當要求使...