1. 程式人生 > >C++中volatile

C++中volatile

情況下 body 阻止 最新 code 進入 lock 其它 代碼

volatile只保證其“可見性”,不保證其“原子性”。

執行count++;這條語句由3條指令組成:

(1)將 count 的值從內存加載到 cpu 的某個 寄存器r;

(2)將 寄存器r 的值 +1,結果存放在 寄存器s;

(3)將 寄存器s 中的值寫回內存。

所以,如果有多個線程同時在執行 count++,在某個線程執行完第(3)步之前,其它線程是看不到它的執行結果的。(這裏有疑惑:線程同時執行count++,為了保證其原子性,為何不加mutex lock?而是尋求volatile?)

在沒有volatile的時候,執行完count++,執行結果其實是寫到CPU緩存中,沒有馬上寫回到內存中,後續在某些情況下(比如CPU緩存不夠用)再將CPU緩存中的值flush到內存。因為沒有存到內存裏,其他線程是不能及時看到執行結果的。

在有volatile的時候,執行完count++,執行結果寫入緩存中,並同時寫入內存中,所以可以保證其它線程馬上看到執行的結果。

但是,volatile 並沒有保證原子性,在某個線程執行(1)(2)(3)的時候,volatile 並沒有鎖定 count 的值,也就是並不能阻塞其他線程也執行(1)(2)(3)。可能有兩個線程同時執行(1),所以(2)計算出來一樣的結果,然後(3)存回的也是同一個值。 考慮下面一段代碼:
1 int some_int = 100;
2 
3 while(some_int == 100)
4 {
5    //your code
6 }

這時候,編譯器會優化代碼為:

1 //your code

因為編譯器認為some_int沒被改變過,一直是100。但是在多線程時,如果執行完第一行,但是還沒執行到第三行時,另一個線程修改了some_int,while就不能進入循環了。加了volatile後,阻止了編譯器優化,每次讀到some_int會從內存中讀取,而不是本線程的寄存去(當然這會損失效率)。這就是volatile的作用。

一句話總結:volatile保證線程能讀到最新的數據,因為是從內存中讀取,且存入內存中。而不是線程各自的寄存器中讀寫。 疑問: 我知道how volatile works,但是為何要保證其“可見性”呢?有一直需求可能是某個線程在監視某個變量,而這個變量可以被很多線程調用。我理解的對嗎?如果是這樣的話,多線程之間用static可以麽,只存一份值,難道寄存器也會優化嗎? 答: 既然static已經是全局唯一了,那應該就是線程間共享,因此一個線程改變它其它線程都能看到,可惜這並不是事實,為了提高優化度和運行速度,一個線程修改這個變量是不一定立即寫回內存讓其它線程看到的,這時候就需要用volatile強制要求每次改變都寫回內存了。

C++中volatile