正文
在嵌入式軟件開(kāi)發(fā)過(guò)程中,如果對(duì)volatile不熟,那可以你應(yīng)該是個(gè)"假嵌入式程序員",因?yàn)橐粋€(gè)變量需不需要使用volatile考慮的場(chǎng)景挺多的,如果在某些場(chǎng)景下亂用,會(huì)影響程序運(yùn)行效率,有時(shí)候忘記加甚至?xí)沟贸绦虬l(fā)生異常,那么bug菌今天就大家好好聊聊這個(gè)C語(yǔ)言關(guān)鍵字:
1
傳統(tǒng)定義
volatile直譯為“易變的”,也就是告訴編譯器這個(gè)變量隨時(shí)都可能發(fā)生變化,編譯器你跟我“特殊照顧一下“。
那么編譯器通常會(huì)怎么去處理使用volatile修飾的變量呢?
對(duì)于C變量都是代表著對(duì)應(yīng)的內(nèi)存,讀取使用volatile修飾的變量,會(huì)直接從其所對(duì)應(yīng)的內(nèi)存地址中獲取最新的數(shù)據(jù),否則,編譯器會(huì)對(duì)其訪問(wèn)進(jìn)行優(yōu)化,比如直接從緩存中讀取副本、或者是從寄存器中讀取副本。
這樣就可能會(huì)導(dǎo)致數(shù)據(jù)更新不一致的問(wèn)題。
2
最常用的地方
從前面對(duì)volatile的功能描述,我們可以知道volatile最常用于那些與硬件外設(shè)寄存器打交道的地址,這樣確保每次對(duì)寄存器的讀取都是從內(nèi)存中獲取的最新值,比如:
再比如下圖所示,如果我們向地址0x812100地址連續(xù)改變其值:
那么編譯器通常會(huì)將其直接優(yōu)化為第三條操作,并不會(huì)去執(zhí)行前兩條操作,這樣會(huì)造成寫(xiě)寄存器時(shí)序上的問(wèn)題。
如果采用volatile去修飾,則三條命令便會(huì)依次執(zhí)行,達(dá)到我們代碼所示三次操作的目的。
3
更復(fù)雜一點(diǎn)的,也是最重要的
其實(shí)對(duì)于volatile所解決的問(wèn)題用更加專(zhuān)業(yè)的說(shuō)法可以分為:可見(jiàn)性和有序性。
1、可見(jiàn)性
所謂可見(jiàn)性,通常是在多線程訪問(wèn)共享數(shù)據(jù)的情況,當(dāng)一個(gè)線程對(duì)共享變量進(jìn)行修改,而其他線程能否立即觀察到這個(gè)修改的性質(zhì)。
在我們目前大部分單核一級(jí)緩存的CPU無(wú)需考慮這個(gè)問(wèn)題,而對(duì)于現(xiàn)場(chǎng)多核多級(jí)緩存處理器,各個(gè)現(xiàn)場(chǎng)都會(huì)維護(hù)著自己的緩存,如果僅僅只是更新到了自己的緩存中那么其他線程是無(wú)法立馬感受到這個(gè)修改的,最終導(dǎo)致結(jié)果不一致。
2、有序性
很多時(shí)候也叫作重排序,說(shuō)白了就是對(duì)執(zhí)行指令進(jìn)行了執(zhí)行順序上的優(yōu)化,以不改變指令運(yùn)行的最終結(jié)果,而改變指令的執(zhí)行順序。
編譯器可以調(diào)整指令,同樣處理器的多級(jí)流水線和亂序執(zhí)行也同樣可以改變指令執(zhí)行順序;甚至為了多級(jí)緩存的高效執(zhí)行,也同樣會(huì)對(duì)內(nèi)存讀寫(xiě)操作進(jìn)行重排序。
然而這樣的重排序,卻會(huì)對(duì)多線程并發(fā)訪問(wèn)共享數(shù)據(jù)的過(guò)程中產(chǎn)生問(wèn)題,從而不符合我們編程源碼的預(yù)期執(zhí)行順序。
但對(duì)于volatile只能在一定程度上防止指令重排序,其只能保證單個(gè)變量訪問(wèn)的有序性,而不能保證整個(gè)程序的有序性,所以這一點(diǎn)是大家尤為要注意的。
所以講了這么多,相信以后大家再開(kāi)發(fā)中也都會(huì)遇到。
審核編輯:劉清
-
寄存器
+關(guān)注
關(guān)注
31文章
5421瀏覽量
123373 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7630瀏覽量
140426 -
嵌入式軟件
+關(guān)注
關(guān)注
4文章
245瀏覽量
27177 -
volatile
+關(guān)注
關(guān)注
0文章
46瀏覽量
13277
原文標(biāo)題:這個(gè)變量要不要用volatile修飾呢?
文章出處:【微信號(hào):最后一個(gè)bug,微信公眾號(hào):最后一個(gè)bug】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
volatile 釋義
【原創(chuàng)分享】單片機(jī)編程關(guān)鍵字之volatile
volatile關(guān)鍵字應(yīng)用場(chǎng)景及示例
編譯器之位域和volatile研究
C語(yǔ)言中的volatile關(guān)鍵字
Volatile與多線程的認(rèn)識(shí)與理解
volatile變量定義的意義和該用在哪里

C語(yǔ)言類(lèi)型修飾符Volatile的使用說(shuō)明
WIN和AVR及AVR-GCC中如何使用volatile的詳細(xì)資料概述

關(guān)于volatile關(guān)鍵字對(duì)編譯器優(yōu)化的影響
如何使用C++語(yǔ)法中的volatile
C++基礎(chǔ)語(yǔ)法之volatile、assert()和sizeof()
漫談C變量——優(yōu)化天敵“volatile”

評(píng)論