正文
在嵌入式軟件開發過程中,如果對volatile不熟,那可以你應該是個"假嵌入式程序員",因為一個變量需不需要使用volatile考慮的場景挺多的,如果在某些場景下亂用,會影響程序運行效率,有時候忘記加甚至會使得程序發生異常,那么bug菌今天就大家好好聊聊這個C語言關鍵字:
1
傳統定義
volatile直譯為“易變的”,也就是告訴編譯器這個變量隨時都可能發生變化,編譯器你跟我“特殊照顧一下“。
那么編譯器通常會怎么去處理使用volatile修飾的變量呢?
對于C變量都是代表著對應的內存,讀取使用volatile修飾的變量,會直接從其所對應的內存地址中獲取最新的數據,否則,編譯器會對其訪問進行優化,比如直接從緩存中讀取副本、或者是從寄存器中讀取副本。
這樣就可能會導致數據更新不一致的問題。
2
最常用的地方
從前面對volatile的功能描述,我們可以知道volatile最常用于那些與硬件外設寄存器打交道的地址,這樣確保每次對寄存器的讀取都是從內存中獲取的最新值,比如:
再比如下圖所示,如果我們向地址0x812100地址連續改變其值:
那么編譯器通常會將其直接優化為第三條操作,并不會去執行前兩條操作,這樣會造成寫寄存器時序上的問題。
如果采用volatile去修飾,則三條命令便會依次執行,達到我們代碼所示三次操作的目的。
3
更復雜一點的,也是最重要的
其實對于volatile所解決的問題用更加專業的說法可以分為:可見性和有序性。
1、可見性
所謂可見性,通常是在多線程訪問共享數據的情況,當一個線程對共享變量進行修改,而其他線程能否立即觀察到這個修改的性質。
在我們目前大部分單核一級緩存的CPU無需考慮這個問題,而對于現場多核多級緩存處理器,各個現場都會維護著自己的緩存,如果僅僅只是更新到了自己的緩存中那么其他線程是無法立馬感受到這個修改的,最終導致結果不一致。
2、有序性
很多時候也叫作重排序,說白了就是對執行指令進行了執行順序上的優化,以不改變指令運行的最終結果,而改變指令的執行順序。
編譯器可以調整指令,同樣處理器的多級流水線和亂序執行也同樣可以改變指令執行順序;甚至為了多級緩存的高效執行,也同樣會對內存讀寫操作進行重排序。
然而這樣的重排序,卻會對多線程并發訪問共享數據的過程中產生問題,從而不符合我們編程源碼的預期執行順序。
但對于volatile只能在一定程度上防止指令重排序,其只能保證單個變量訪問的有序性,而不能保證整個程序的有序性,所以這一點是大家尤為要注意的。
所以講了這么多,相信以后大家再開發中也都會遇到。
審核編輯:劉清
-
寄存器
+關注
關注
31文章
5250瀏覽量
119192 -
C語言
+關注
關注
180文章
7575瀏覽量
134017 -
嵌入式軟件
+關注
關注
4文章
238瀏覽量
26550 -
volatile
+關注
關注
0文章
44瀏覽量
12979
原文標題:這個變量要不要用volatile修飾呢?
文章出處:【微信號:最后一個bug,微信公眾號:最后一個bug】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論