1. 程式人生 > >Java多執行緒程式設計核心技術之volatile關鍵字

Java多執行緒程式設計核心技術之volatile關鍵字

volatile與死迴圈        

        在64bit的JVM上以“-server”伺服器模式執行java執行緒類程式碼時,為了保證在該模式下保障執行緒執行的效率,執行緒會一直在私有堆疊中取值,而volatile關鍵字的作用是強制從公共堆疊中取得變數值,這樣就能有效的解決死迴圈狀態。

        使用volatile關鍵字增加了例項變數在多個執行緒之間的可見性。但volatile關鍵字最致命的缺點是不支援原子性。

下面將關鍵字synchronized和volatile進行比較

(1)關鍵字volatile是執行緒同步的輕量級實現,所以volatile效能肯定比synchronized要好,並且volatile只能修飾於變數,而synchronized可以修飾方法,以及程式碼塊。隨著JDK版本的釋出,synchronized關鍵字在執行效率上得到很大的提升,在開發中使用synchronized關鍵字的比率還是比較大的。

(2)多執行緒訪問volatile不會發生阻塞,而synchronized會出現阻塞。

(3)volatile能保證資料的可見性,但不保證原子性;而synchronized可以保證原子性,也可以間接保證可見性,因為它會將私有記憶體和公共記憶體中的資料做同步。

(4)關鍵字volatile解決的是變數在多個執行緒間的可見性;而synchronized解決的是多個執行緒之間訪問資源的同步性。

volatile的使用場景

        關鍵字volatile主要使用的場景是在多個執行緒中可以感知例項變數被更改了,並且可以獲得最新的值使用,也就是用多執行緒讀取共享變數時可以獲得新值使用。

volatile出現非執行緒安全的原因

(1)read和load階段:從主記憶體複製變數到當前執行緒工作記憶體;

(2)use和assign階段:執行程式碼,改變共享變數值;

(3)store和write階段:用工作記憶體資料重新整理主存對應變數的值。

        在多執行緒環境中,use和assign是多次出現的,但這一操作並不是原子性的,也就是在read和load之後,如果主記憶體count變數發生修改後,執行緒工作記憶體中的值由於已經載入,不會發生對應的變化,也就是私有記憶體和公共記憶體中的變數不同步,所以計算出來的結果回合預期的不一樣,也就出現了非執行緒安全問題。

        對於多個執行緒訪問同一個例項變數還是需要加鎖同步。