為什麼volatile不能保證原子性

2021-08-10 11:22:39 字數 861 閱讀 8911

原子操作

簡單來說,原子操作(atomic)就是不可分割的操作,在計算機中,就是指不會因為新城排程被打斷的操作。

比如,簡單的賦值就是乙個原子操作:

m =6  //這是個原子操作
假如m原先的值為0,那麼對於這個操作,要麼執行成功m程式設計了6,要麼沒執行m還是0,而不會出現諸如m=3,這種中間狀態。

但是宣告並賦值就不是乙個原子操作:

int n = 6; //這個不是乙個原子操作
對於這個語句至少會有來個操作:

①宣告乙個變數n

②給n賦值為6

這樣就會有乙個中間狀態:變數n已經被宣告了但是還沒有被賦值的狀態。在多執行緒中,由於執行緒執行順序的不確定性,如果兩個執行緒都使用m,就可能會導致不穩定的結果出現。

指令重排
簡單來說,就是計算機為了提高執行效率,會做的一些優化,在不影響最終結果的情況下,可能會對一些語句的執行順序進行調整。

比如,這一段**:

int a ;   // 語句1 

a = 8 ; // 語句2

int b = 9 ; // 語句3

int c = a + b ; // 語句4

正常來說,對於順序結構,執行的順序是自上到下,也即1234。但是,由於指令重排的原因,因為不影響最終的結果,所以,實際執行的順序可能會變成3124或者1324。由於語句3和4沒有原子性的問題,語句3和語句4也可能會拆分成原子操作,再重排。——也就是說,對於非原子性的操作,在不影響最終結果的情況下,其拆分成的原子操作可能會被重新排列執行順序。

volatile為什麼不能保證原子性?

我們來看一下jmm是如何解釋的jmm規定了所有的變數都儲存在主記憶體 main memory 中,多個執行緒共享主記憶體中 的資料。每個執行緒都有自己的工作記憶體 working memory 執行緒的工作記憶體中保 存了該執行緒使用到的變數在主記憶體的副本拷貝,執行緒對變數的所有操作 讀取 賦 值...

volatile為什麼不能保證變數原子性

看個例子,僅是個人理解。public class volatiledemo 當進行自增操作,位元組碼是這樣的 1 獲取變數的值併入棧 2 把1入棧 3 依次取出棧中兩個運算元相加併入棧 假設為臨時變數t 4 取出棧頂值賦值給變數 而volatile的可見性指的是第4步,當修改變數後,把新值重新整理到...

volatile不能保證原子性

在討論原子性操作時,我們經常會聽到乙個說法 任意單個volatile變數的讀寫具有原子性,但是volatile 這種操作除外。所以問題就是 為什麼volatile 不是原子性的?因為它實際上是三個操作組成的乙個符合操作。首先獲取volatile變數的值 將該變數的值加1 將該volatile變數的值...