咱們日常在看開源項目的源碼時,常常可以看到某些類變量定義爲volatile,可是每每在本身編程的時候,卻又不多用到,那在這篇小短文中,我會跟你們解釋如何正確的使用volatile關鍵字。
在Java中,每個線程有獨立的工做內存區域。Java對象的變量值就保存在這些獨立的工做內存區域裏。因爲線程的工做內存是獨立於主內存的,這就涉及到JVM須要將變量從主內存拷貝到線程工做內存,若是線程對變量進行了寫操做,JVM並無保證什麼時候將工做內存的變量值同步到主內存,這樣就存在着變量值不一樣步的風險。Java的volatile關鍵字就是用來將類變量定義爲多線程只在主內存中對變量進行讀寫操做。編程
Java的volatile關鍵字旨在解決變量可見性問題。經過聲明計數器變量volatile,全部寫入計數器變量將當即寫入主存。此外,計數器變量的全部讀取都將直接從主存儲器讀取。多線程
public class VolatileExample { private volatile int count = 0; public void increament() { count++; } public int getCount() { return count; } }
如上面代碼所示,將變量聲明爲volatile能夠保證對該變量的其餘寫入線程的可見性。在上面給出的方案中,一個線程(線程1)修改了計數器,而另外一個線程(線程2)讀取了計數器(但從未修改過),聲明計數器變量爲volatile足以確保線程2寫入計數器變量的可見性。
可是,若是線程1和線程2都在增長計數器變量,那麼僅聲明計數器變量爲volatile是不夠的,程序依然會有併發衝突的風險。咱們能夠經過使用Java提供的原子數據類型(例如AtomicInt或AtomicLong)來避免併發衝突。併發
對於全部多線程應用程序,咱們須要確保幾個規則以實現一致的行爲:性能
雖然同步方法和代碼塊能夠實現上述兩個規則,可是是以犧牲程序性能爲代價的。因此volatile是在有些多線程的場景下很是有用的方式,能夠幫助確保數據更改的可見性,可是又不須要用到性能開銷較大的同步鎖(synchronized)。線程