1、當乙個變數可能會被意想不到的更新時,要使用volatile來宣告該變數,告訴編譯器它所修飾的變數的值可能會在任何時刻被意外的更新。
2、語法
volatile int foo;
int volatile foo;
volatile int * foo;
int volatile * foo;
int * volatile foo;
int volatile * volatile foo;
3、場景
1)並行裝置的硬體暫存器(如狀態暫存器)
假設我們有乙個8位的狀態暫存器對映在位址0x1234上。系統需要我們一直監測狀態暫存器的值,直到它的值不為0為止。通常錯誤的實現方法是:
uint1 * ptr = (uint1 *) 0x1234;
// wait for register to become non-zero.等待暫存器為非0值
while (*ptr == 0);
// do something else.作其他事情
彙編**:
mov ptr, #0x1234
mov a, @ptr
loop bz loop 編譯器認為變數值總是不變的,不必要到記憶體中讀取它,使用乙個無限迴圈來結束
正確:uint1 volatile * ptr =
(uint1 volatile *) 0x1234;
對應的彙編**為:
mov ptr, #0x1234
loop mov a, @ptr
bz loop
2)中斷處理程式
中斷處理程式經常負責更新一些在主程式中被查詢的變數的值。例如,乙個序列通訊中斷會檢測接收到的每乙個位元組是否為etx訊號(以便來確認乙個訊息幀的結束標誌)。如果其中的乙個位元組為etx,中斷處理程式就是修改乙個全域性標誌。乙個錯誤的實現方法可能為:
int etx_rcvd = false;
void main()
...}
interrupt void rx_isr(void)
...}
3)多執行緒應用程式
在實時作業系統中,除去佇列、管道以及其他排程相關的通訊結構,在兩個任務之間採用共享的記憶體空間(就是全域性共享)實現資料的交換仍然是相當常見的方法。當你將乙個優先權排程器應用於你的**時,編譯器仍然不知道某一程式段分支選擇的實際工作方式以及什麼時候某一分支情況會發生。這是因為,另外乙個任務修改乙個共享的全域性變數在概念上通常和前面中斷處理程式中提到的情形是一樣的。所以,(這種情況下)所有共享的全域性變數都要被宣告為 volatile。例如:
int cntr;
void task1(void)
...}
void task2(void)
4)利用for迴圈去延時的程式
volatile的應用場景
下面先來想一下單例模式中的雙端檢查 public class singleton private static singleton getinstance return instance 思考這樣乙個場景 有兩個執行緒,執行緒a和執行緒b,執行緒a是初次訪問getinstance 方法,此時在第乙個...
volatile的用法和實際應用場景
1 volatile提醒編譯器它後面所定義的變數隨時有可能改變,因此編譯後的程式每次需要儲存或讀取這個變數的時候,都要小心地。從該變數的位址中讀取。如果沒有volatile關鍵字,則編譯器就可能優化讀取和儲存,可能暫時使用暫存器中的值。當要求使用volatile宣告變數的時候,系統總是重新從它所在的...
volatile的使用場景
單詞解釋 亂序執行 指cpu對 的執行順序進行亂序優化,但保證各執行 單元的順序按指令順序排列。以達到充分利用處理器的各處理單元的目的。可以理解成 乙個任務有不同的執行單元,這些單元之間有一定的執行順序,但部分執行單元可提前工作,亂序執行就是讓這部分執行單元提前一段時間執行,從而提高整體的效率,減少...