volatile和synchronized

=================================================
原文鏈接http://blog.csdn.net/suifeng3051/article/details/52611233,如侵刪
=================================================

volatile和synchronized特點

首先需要理解線程安全的兩個方面:執行控制內存可見

執行控制的目的是控制代碼執行(順序)及是否可以併發執行。

內存可見控制的是線程執行結果在內存中對其它線程的可見性。根據Java內存模型的實現,線程在具體執行時,會先拷貝主存數據到線程本地(CPU緩存),操作完成後再把結果從線程本地刷到主存。

synchronized關鍵字解決的是執行控制的問題,它會阻止其它線程獲取當前對象的監控鎖,這樣就使得當前對象中被synchronized關鍵字保護的代碼塊無法被其它線程訪問,也就無法併發執行。更重要的是,synchronized還會創建一個內存屏障,內存屏障指令保證了所有CPU操作結果都會直接刷到主存中,從而保證了操作的內存可見性,同時也使得先獲得這個鎖的線程的所有操作,都happens-before於隨後獲得這個鎖的線程的操作。

volatile關鍵字解決的是內存可見性的問題,會使得所有對volatile變量的讀寫都會直接刷到主存,即保證了變量的可見性。這樣就能滿足一些對變量可見性有要求而對讀取順序沒有要求的需求。

使用volatile關鍵字僅能實現對原始變量(如boolen、 short 、int 、long等)操作的原子性,但需要特別注意, volatile不能保證複合操作的原子性,即使只是i++,實際上也是由多個原子操作組成:read i; inc; write i,假如多個線程同時執行i++volatile只能保證他們操作的i是同一塊內存,但依然可能出現寫入髒數據的情況。

在Java 5提供了原子數據類型atomic wrapper classes,對它們的increase之類的操作都是原子操作,不需要使用sychronized關鍵字。

對於volatile關鍵字,當且僅當滿足以下所有條件時可使用:

1. 對變量的寫入操作不依賴變量的當前值,或者你能確保只有單個線程更新變量的值。
2. 該變量沒有包含在具有其他變量的不變式中。
  • 1
  • 2
  • 3

volatile和synchronized的區別

  1. volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
  2. volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
  3. volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性
  4. volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
  5. volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化

如果想更好地理解這兩個關鍵字的作用,強烈建議看一下這篇文章:Java內存模型

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章