1. 程式人生 > >volatile簡單理解

volatile簡單理解

通過java記憶體模型理解

程式碼例子理解:

作者:KE meng
連結:https://www.zhihu.com/question/31459750/answer/52061391
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

來看這個程式碼:

int fun(int& a)
{
    int b = a;
    int c = a;
    return a+b+c;
}

int main()
{
    int a=1;
    //.........做一些和a無關的事
    return fun(a);
}

這個程式碼是很好優化的,因為編譯器知道a的值是1,參考上下文,編譯器又能知道b和c的值也是1,

而且根本沒有人用到了a,b,c三個變數,也沒有任何人在修改a,b,c三個的值,所以編譯器可能就直接

把這個函式優化成:

int main() { return 3; }

了.

這麼優化有什麼問題嗎? 單執行緒沒問題,但多執行緒就有問題了,如果是多執行緒,
a的值雖然在當前上下文中不會被修改,但可能正在被其他執行緒修改啊.於是上面的優化
就不對了. 那麼,volatile關鍵字在這裡就可以幫助我們了,volatile關鍵字提醒編譯器:
a可能隨時被意外

修改.
意外的意思是雖然當前這段程式碼裡看起來a不會變,但可能別的地方正在修改a的值哦.
所謂"別的地方",某些情況下指的就是其他執行緒了.

那麼,如果把程式碼修改如下:

int fun(volatile int& a)
{
    int b = a;
    int c = a;
    return a+b+c;
}

int main()
{
    volatile int a=1;
    //.........做一些和a無關的事
    return fun(a);
}

編譯器就不敢優化了:

int fun(volatile int& a)
{
    int b = a; //這裡從記憶體讀一下a吧,誰知道a還等不等於1呢
    int c = a; //這裡再從記憶體讀一下a吧,誰知道a還等不等於1呢
    return a+b+c;  //這裡也從記憶體讀一下a吧,誰知道a還等不等於1呢
}

int main()
{
    volatile int a=1;
    //.........做一些和a無關的事
    return fun(a); //完全不敢優化啊,鬼知道a變成多少了....
}



總結:被volatile修飾的變數,有執行緒使用到該變數時都會去主記憶體裡面讀取以保證“最新”。

加鎖物件obj:A執行緒使用了obj,此時B執行緒無法使用,A執行緒操作obj時直接使用自己工作記憶體中的obj副本,但不保證A執行緒在使用

的obj副本是最新的。

加鎖物件obj並用volatile:A執行緒使用obj,此時B執行緒無法使用,並且obj是從主記憶體中取的,在加鎖的情況下可以保證該obj是最新的。