volatile 和 synchronized 的比較

1,volatile
   它所修飾的變量不保留拷貝,直接訪問主內存中的。
   在 Java 內存模型中,有 main memory,每一個線程也有本身的 memory (例如寄存器)。爲了性能,一個線程會在本身的 memory 中保持要訪問的變量的副本。這樣就會出現同一個變 量在某個瞬間,在一個線程的 memory 中的值可能與另一個線程 memory 中的值,或者 main memory 中的值不一致的狀況。一個變量聲明爲 volatile,就意味着這個變量是隨時會被其餘線程修改的,所以不能將它 cache 在線程memory 中。



2,synchronizedjava

      當它用來修飾一個方法或者一個代碼塊的時候,可以保證在同一時刻最多隻有一個線程執行該段代碼。緩存

     1、當兩個併發線程訪問同一個對象 objec t中的這個 synchronized(this) 同步代碼塊時,一個時間內只能有一個線程獲得執行。另外一個線程必須等待當前線程執行完這個代碼塊之後才能執行該代碼塊。併發

     2、然而,當一個線程訪問 object 的一個 synchronized(this) 同步代碼塊時,另外一個線程仍然能夠訪問該 object 中的非 synchronized(this)同步代碼塊。性能

     3、尤爲關鍵的是,當一個線程訪問 object 的一個 synchronized(this) 同步代碼塊時,其餘線程對 object 中全部其它 synchronized(this) 同步代碼塊的訪問將被阻塞。學習

     4、當一個線程訪問 object 的一個 synchronized(this) 同步代碼塊時,它就得到了這個 object 的對象鎖。結果,其它線程對該 object 對象全部同步代碼部分的訪問都被暫時阻塞。this

     5、以上規則對其它對象鎖一樣適用.spa

 

區別:線程

 1、volatile 是變量修飾符,而 synchronized 則做用於一段代碼或方法。code

 2、volatile 只是在線程內存和「主」內存間同步某個變量的值;而 synchronized 經過鎖定和解鎖某個監視器同步全部變量的值。顯然synchronized 要比 volatile 消耗更多資源。 對象

 3、volatile 不能保證操做的原子性。synchronized 能夠保證操做的原子性。

那麼請參考以下:

volatile 不能保證操做的原子性。synchronized 能夠保證操做的原子性。我認爲這是他們最大的區別。

此外 volatile 是變量修飾符,而 synchronized 是要修飾一段代碼或者方法

 

那麼volatile是幹什麼的呢?

volatile是變量修飾符。被它修飾的變量不會在線程中保留備份(注:能夠這麼理解,可是其內部機制應該仍是保留了備份的,只不過是經過特殊的機制實時的將線程中變量的值更新到i)。這樣就不會出現上述線程A B 和主內存的值不同的狀況。

可是注意:volatile並不能保證操做的原子性。即便只是i++,實際上也是由多個原子操做組成:read i; inc; write i,假如多個線程同時執行i++,依然可能出現寫入髒數據的狀況。它只不過是保證各個線程操做的是同一起內存而已。

synchronized 爲何能保證操做的原子性呢?

這得從它的工做機制提及,很明顯 synchronized 可以保證被它修飾的一段代碼同一個時刻只被同一個線程執行。

事實上它同步代碼的過程也在同步內存。

假若有以下代碼:

public class Test implements Runnable{

      private int i=1;

      public void run(){

          operate();

      }


      public synchronized void operate(){

            i = 2;

     }

}

當線程A執行方法operate的時候將進行以下步驟:

1.線程請求this的鎖,若是鎖被其餘的線程佔用就進入阻塞狀態直到鎖被釋放。

2.線程內存中緩存的數據被清除,從主內存中read/load讀入最新的值。

3.synchronized內的代碼塊被執行,在此執行過程當中其對應的主內存不會被其餘的線程使用。

4.執行完畢釋放鎖。

 

水平有限,如有問題請留言交流!

互相學習,共同進步 :)轉載請註明出處謝謝!

相關文章
相關標籤/搜索