首頁  >  文章  >  Java  >  Java中關鍵字volatile 和 synchronized 的作用和區別

Java中關鍵字volatile 和 synchronized 的作用和區別

巴扎黑
巴扎黑原創
2017-06-26 10:20:181622瀏覽

 

volatile是變數修飾符,而synchronized則是作用於一段程式碼或方法;如下三個get方法的程式碼:

1 int i1;2 int geti1() {return i1;}3 4 volatile int i2;5 int geti2() {return i2;}6 7 int i3;8 synchronized int geti3() {return i3;}

    geti1() 得到儲存在目前執行緒中i1的數值。多個執行緒有多個i1變數拷貝,而且這些i1之間可以互相不同。換句話說,另一個執行緒可能已經改變了它執行緒內的i1值,而這個值可以和目前執行緒中的i1值不相同。 在Java記憶體模型中,有main memory(主記憶體區域),這裡存放了變數目前的“準確值”,每個執行緒也有自己的memory(例如暫存器)。為了效能,一個執行緒會在自己的memory中保存要存取的變數的副本。這樣就會出現同一個變數在某個瞬間,在一個執行緒的memory中的值可能與另外一個執行緒memory的值,或是main memory的值不一致的情況。因此實際上存在一種可能:main memory的值i1值是1,線程1裡的i1是2,線程2裡的i1值是3,這在線程1和線程2都改變了他們各自的i1值,而且這個改變還來不及傳給main memory 或其他執行緒時就會發生。

    geti2() 得到的是main memory的i2數值。 一個變數宣告為volatile,就表示這個變數是隨時會被其他執行緒修改的,因此不能將它cache在執行緒memory中。 換句話說,一個變數經過volatile修飾後在所有執行緒中必須是同步的,任何執行緒中改變了它的值,所有其他執行緒立即獲得了相同的值。所以,volatile修飾的變數存取時比一般變數消耗的資源多一點,因為執行緒有它自己的變數拷貝更有效率。

    geti3()方法被synchronized修飾,用synchronized來修飾一個方法或一個程式碼的時候,能夠保證在同一時刻最多只有一個執行緒執行該段程式碼。既然volatile關鍵字已經實現了執行緒間資料同步,又要synchronized幹嘛?當兩個並發執行緒存取同一個物件object中的這個synchronized(this)同步程式碼時,一個時間內只能有一個執行緒來執行。另一個執行緒必須等待目前執行緒執行完這個程式碼區塊才能執行該程式碼區塊。然而,當一個執行緒存取object的一個synchronized(this)同步程式碼區塊時,另一個執行緒仍然可以存取該object中的非synchronized(this)同步程式碼區塊。尤其關鍵的是,當一個執行緒存取object的一個synchronized(this)同步程式碼區塊時候,其他執行緒對object中所有其他synchronized(this)同步程式碼區塊的存取將被阻塞。當一個執行緒存取object的一個synchronized(this)同步程式碼區塊時,它就獲得了這個object的物件鎖,結果,其他執行緒對該物件所有同步程式碼部分的存取都被暫時阻塞。

    總結一下差異

    一,volatile是變數修飾符,而synchronized則作用於一段程式碼或方法。

    二,volatile只是在執行緒記憶體和main memory(主記憶體)間同步某個變數的值;而synchronized透過鎖定和解鎖某個監視器同步所有變數的值。顯然synchronized要比volatile消耗更多資源。

 

以上是Java中關鍵字volatile 和 synchronized 的作用和區別的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn