0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

編譯器通常會(huì)怎么去處理使用volatile修飾的變量呢?

lilihe92 ? 來源:最后一個(gè)bug ? 2023-11-29 10:05 ? 次閱讀

正文

嵌入式軟件開發(fā)過程中,如果對(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ì)其訪問進(jìn)行優(yōu)化,比如直接從緩存中讀取副本、或者是從寄存器中讀取副本。

這樣就可能會(huì)導(dǎo)致數(shù)據(jù)更新不一致的問題。

2

最常用的地方

從前面對(duì)volatile的功能描述,我們可以知道volatile最常用于那些與硬件外設(shè)寄存器打交道的地址,這樣確保每次對(duì)寄存器的讀取都是從內(nèi)存中獲取的最新值,比如:

2f457242-8df4-11ee-939d-92fbcf53809c.png

再比如下圖所示,如果我們向地址0x812100地址連續(xù)改變其值:

2f58b3ac-8df4-11ee-939d-92fbcf53809c.png

那么編譯器通常會(huì)將其直接優(yōu)化為第三條操作,并不會(huì)去執(zhí)行前兩條操作,這樣會(huì)造成寫寄存器時(shí)序上的問題。

如果采用volatile去修飾,則三條命令便會(huì)依次執(zhí)行,達(dá)到我們代碼所示三次操作的目的。

2f62bf46-8df4-11ee-939d-92fbcf53809c.png

3

更復(fù)雜一點(diǎn)的,也是最重要的

其實(shí)對(duì)于volatile所解決的問題用更加專業(yè)的說法可以分為:可見性和有序性。

1、可見性

所謂可見性,通常是在多線程訪問共享數(shù)據(jù)的情況,當(dāng)一個(gè)線程對(duì)共享變量進(jìn)行修改,而其他線程能否立即觀察到這個(gè)修改的性質(zhì)。

在我們目前大部分單核一級(jí)緩存的CPU無需考慮這個(gè)問題,而對(duì)于現(xiàn)場(chǎng)多核多級(jí)緩存處理器,各個(gè)現(xiàn)場(chǎng)都會(huì)維護(hù)著自己的緩存,如果僅僅只是更新到了自己的緩存中那么其他線程是無法立馬感受到這個(gè)修改的,最終導(dǎo)致結(jié)果不一致。

2、有序性

很多時(shí)候也叫作重排序,說白了就是對(duì)執(zhí)行指令進(jìn)行了執(zhí)行順序上的優(yōu)化,以不改變指令運(yùn)行的最終結(jié)果,而改變指令的執(zhí)行順序。

編譯器可以調(diào)整指令,同樣處理器的多級(jí)流水線和亂序執(zhí)行也同樣可以改變指令執(zhí)行順序;甚至為了多級(jí)緩存的高效執(zhí)行,也同樣會(huì)對(duì)內(nèi)存讀寫操作進(jìn)行重排序。

然而這樣的重排序,卻會(huì)對(duì)多線程并發(fā)訪問共享數(shù)據(jù)的過程中產(chǎn)生問題,從而不符合我們編程源碼的預(yù)期執(zhí)行順序。

但對(duì)于volatile只能在一定程度上防止指令重排序,其只能保證單個(gè)變量訪問的有序性,而不能保證整個(gè)程序的有序性,所以這一點(diǎn)是大家尤為要注意的。

所以講了這么多,相信以后大家再開發(fā)中也都會(huì)遇到。







審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5359

    瀏覽量

    120803
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7614

    瀏覽量

    137249
  • 嵌入式軟件
    +關(guān)注

    關(guān)注

    4

    文章

    240

    瀏覽量

    26673
  • volatile
    +關(guān)注

    關(guān)注

    0

    文章

    45

    瀏覽量

    13041

原文標(biāo)題:這個(gè)變量要不要用volatile修飾呢?

文章出處:【微信號(hào):最后一個(gè)bug,微信公眾號(hào):最后一個(gè)bug】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    volatile 釋義

    取出i的值,因而編譯器生成的匯編代碼會(huì)重新從內(nèi)存中i的地址處讀取i的值存放在k中。一句話概括就是,當(dāng)用volatile關(guān)鍵字修飾變量時(shí),優(yōu)化
    發(fā)表于 08-05 16:06

    【原創(chuàng)分享】單片機(jī)編程關(guān)鍵字之volatile

    ,那么兩個(gè)線程有可能一個(gè)使用內(nèi)存中的變量,一個(gè)使用寄存中的變量,這回造成程序的錯(cuò)誤執(zhí)行。那么用了volatile修飾
    發(fā)表于 06-29 11:17

    volatile關(guān)鍵字應(yīng)用場(chǎng)景及示例

    volatile關(guān)鍵字1.應(yīng)用場(chǎng)景2.示例1.應(yīng)用場(chǎng)景volatile關(guān)鍵字分析,往往應(yīng)用在三種場(chǎng)合1)多線程編程共享全局變量的時(shí)候,該全局變量要加上
    發(fā)表于 08-24 07:21

    編譯器之位域和volatile研究

    1、位域和volatile介紹  位域和volatile大家再熟悉不過了:前者用于將指定類型的整形變量按照我們的意愿像蛋糕一樣切分成或大或小的若干份;后者用于告訴編譯器“絕不允許對(duì)被
    發(fā)表于 11-11 18:09

    C語(yǔ)言中的volatile關(guān)鍵字

    volatile關(guān)鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改。
    發(fā)表于 05-27 09:32 ?3277次閱讀

    Volatile與多線程的認(rèn)識(shí)與理解

    不會(huì)因編譯器的優(yōu)化而省略,且要求每次直接讀值。volatile變量是說這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)
    發(fā)表于 12-01 10:31 ?1664次閱讀

    volatile變量定義的意義和該用在哪里

    volatile 影響編譯器編譯的結(jié)果,volatile指出 變量是隨時(shí)可能發(fā)生變化的,與volatil
    發(fā)表于 03-07 15:29 ?3689次閱讀
    <b class='flag-5'>volatile</b><b class='flag-5'>變量</b>定義的意義和該用在哪里

    C語(yǔ)言類型修飾Volatile的使用說明

    ,確保本條指令不會(huì)因編譯器的優(yōu)化而省略,且要求每次直接讀值。volatile變量是說這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)
    的頭像 發(fā)表于 09-19 10:54 ?3567次閱讀

    WIN和AVR及AVR-GCC中如何使用volatile的詳細(xì)資料概述

    volatile 的字面含義是易變的,那么將一個(gè)變量指示為 volatile是什么意思?是告訴編譯器這個(gè)
    發(fā)表于 11-20 17:09 ?2次下載
    WIN和AVR及AVR-GCC中如何使用<b class='flag-5'>volatile</b>的詳細(xì)資料概述

    關(guān)于volatile關(guān)鍵字對(duì)編譯器優(yōu)化的影響

    volatile關(guān)鍵字對(duì)編譯器優(yōu)化的影響
    的頭像 發(fā)表于 02-28 17:15 ?2972次閱讀

    虛擬機(jī):編譯器對(duì)C函數(shù)的名字修飾

    虛擬機(jī):編譯器對(duì)C函數(shù)的名字修飾
    的頭像 發(fā)表于 06-22 11:44 ?2576次閱讀
    虛擬機(jī):<b class='flag-5'>編譯器</b>對(duì)C函數(shù)的名字<b class='flag-5'>修飾</b>

    如何使用C++語(yǔ)法中的volatile

    volatile volatile int i = 10; volatile 關(guān)鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些
    的頭像 發(fā)表于 09-09 09:38 ?1500次閱讀

    C++基礎(chǔ)語(yǔ)法之volatile、assert()和sizeof()

    volatile volatile int i = 10; volatile 關(guān)鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些
    的頭像 發(fā)表于 09-09 09:48 ?1323次閱讀

    漫談C變量——優(yōu)化天敵“volatile

    在前面的文章《編譯器玄學(xué)報(bào)告第一期》中,我們了解到:volatile實(shí)際上是告訴編譯器“絕不允許對(duì)被修飾變量動(dòng)手動(dòng)腳(做優(yōu)化)”,因?yàn)?.
    發(fā)表于 01-25 18:43 ?0次下載
    漫談C<b class='flag-5'>變量</b>——優(yōu)化天敵“<b class='flag-5'>volatile</b>”

    一文詳解volatile關(guān)鍵字

    volatile 是易變的、不穩(wěn)定的意思。和const一樣是一種類型修飾符,volatile關(guān)鍵字修飾變量,
    的頭像 發(fā)表于 02-15 11:54 ?1087次閱讀
    一文詳解<b class='flag-5'>volatile</b>關(guān)鍵字