Java中volatile的併發安全性分析

2021-07-05 03:01:57 字數 1073 閱讀 9055

一、volatile的解釋

當乙個共享變數被volatile修飾時,它會保證修改的值會立即被更新到主存,當有其他執行緒需要讀取時,它會去記憶體中讀取新值。

二、問題的發現

從volatile的定義上來看它看似應該能保證多個執行緒對volatile變數使用的同步,那麼先來看一段**。

package com;

public class main

});threads[i].start();

} // 主線程等待每個執行緒執行完成

for (int i = 0; i < 1000; i++) catch (interruptedexception e)

} //結果如果出現不是1000,則出現了同步問題

system.out.println("執行結果:counter.count=" + main.count);

}}

這段**的執行結果為:

執行結果:counter.count=998

三、分析和結論

從上面**的執行結果上來看,顯然voltile沒有達到我們想要的效果(讓couter=1000),那麼這是什麼原因呢?其實volatile只能保證快取一致性,或者說併發程式設計中的可見性——即乙個執行緒對volatile變數的修改會立即更新到主存,其他執行緒在使用該變數的時候會從主存讀取最新的值。

但是——————它不能保證原子性!!!

我們假設有a、b、c三個執行緒和volatile變數x=0

a——x=1

b——x=x+1

c——x=x+2;

設想如下執**況,(1)a執行完,此時x=1 (2)b、c開始同時執行,從主存中讀取最新的值到工作記憶體

(3)b、c同時執行加運算(4)b寫入主存,c寫入主存

以上執**況並沒有違反volatile的規定,因為b、c同時讀到了最新的值,但是在b寫入主存的時候,c已經執行完加運算,不要讀取最新的x值了,因此連續兩次覆蓋寫入,導致了執行緒同步不理想。

那麼這裡的原子性沒有得到保證是指什麼呢?——讀和寫的操作不是原子性的!

JAVA中的volatile關鍵字

大家最熟悉的保證執行緒安全的技術是lock和synchronized塊 後面就統稱鎖了 但如果在一些對排他性 一會介紹 沒有太多限制的變數上使用鎖會花費很多時間和資源,為了優化程式效能,就有了volatile。鎖提供兩種特性 排他性和可見性。排他性很好理解,就是只有乙個執行緒可以對鎖住的東東進行操作...

Java中的volatile關鍵字

執行緒1 boolean stop false while stop 執行緒2 stop true 第二 使用volatile關鍵字的話,當執行緒2進行修改時,會導致執行緒1的工作記憶體中快取變數stop的快取行無效 反映到硬體層的話,就是cpu的l1或者l2快取中對應的快取行無效 第三 由於執行緒...

java多執行緒中volatile的理解

一 使用runnable來實現多執行緒 package com.xiancheng.old public class threadold implements runnable catch interruptedexception e falg true public boolean isfalg ...