java並發:線程同步機制之Volatile關鍵字&原子操作Atomic


volatile關鍵字

  volatile是一個特殊的修飾符,只有成員變量才能使用它,與Synchronized及ReentrantLock等提供的互斥相比,Synchronized保證了Synchronized同步塊中變量的可見性,而volatile則是保證了所修飾變量的可見性。可見性指的是在一個線程中修改變量的值以后,在其他線程中能夠看到這個值(在Java並發程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的(不可見))。因為volatile只是保證了同一個變量在多線程中的可見性,所以它更多是用於修飾作為開關狀態的變量。

  java關鍵字volatile,從表面意思上是說這個變量是易變的,不穩定的,事實上,確實如此,這個關鍵字的作用就是告訴編譯器,凡是被該關鍵字聲明的變量都是易變的、不穩定的。所以不要試圖對該變量使用緩存等優化機制,而應當每次都從它的內存地址中去讀值。使用volatile標記的變量在讀取或寫入時不需要使用鎖,這將減少產生死鎖的概率,使代碼保持簡潔。

  請注意,這里只是說每次讀取volatile的變量時都要從它的內存地址中讀取,並沒有說每次修改完volatile的變量后都要立刻將它的值寫回內存。也就是說volatile只提供了內存可見性,而沒有提供原子性,操作互斥提供了操作整體的原子性,同一個變量多個線程間的可見性與多個線程中操作互斥是兩件事情,所以說如果用這個關鍵字做高並發的安全機制的話是不可靠的。

volatile的用法如下:

public volatile static int count=0;//在聲明的時候帶上volatile關鍵字即可

  什么時候使用volatile關鍵字?當我們知道了volatile的作用,我們也就知道了它應該用在哪些地方,很顯然,最好是那種只有一個線程修改變量,多個線程讀取變量的地方。也就是對內存可見性要求高,而對原子性要求低的地方。

從上面的描述中,我們可以看出volatile與加鎖機制的主要區別是:加鎖機制既可以確保可見性又可以確保原子性,而volatile變量只有確保可見性。

 

原子操作Atomic

  Volatile變量可以確保先行關系,保證下一個讀取操作會在前一個寫操作之后發生(即寫操作會發生在后續的讀操作之前),但它並不能保證原子性。例如用volatile修飾count變量,那么count++ 操作就不是原子性的。

 

AtomicInteger是基於sun.misc.Unsafe來實現的,其定義如下:

 

該類中有如下一系列方法:

其中某些方法的實現如下:

 

此處再介紹一下AtomicReference,其定義如下:

該類使用了泛型,在定義該類型的變量時需要指定泛型實參,如下:

public final static AtomicReference <String> ATOMIC_REFERENCE = new AtomicReference<String>("abc");

其中String即泛型實參

 

參考資料:

本文從概念上簡單描述了java並發中volatile關鍵字及原子操作atomic的部分內容,此處貼出一些優質文章以供讀者閱覽

(1)http://www.importnew.com/18126.html

(2)http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html

(3)http://www.importnew.com/20594.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM