volatile與synchronized的區別

1、鎖提供了兩種主要特性:互斥(mutual exclusion) 和可見性(visibility)。

  互斥即一次只允許一個線程持有某個特定的鎖,因此可使用該特性實現對共享數據的協調訪問協議,這樣,一次就只有一個線程能夠使用該共享數據。

  可見性要更加複雜一些,它必須確保釋放鎖之前對共享數據做出的更改對於隨後獲得該鎖的另一個線程是可見的 —— 如果沒有同步機制提供的這種可見性保證,線程看到的共享 變量可能是修改前的值或不一致的值,這將引發許多嚴重問題。(競態條件)

2、在Java中,爲了保證多線程讀寫數據時保證數據的一致性,可以採用兩種方式:

  同步:如用synchronized關鍵字,或者使用鎖對象

  使用volatile關鍵字:用一句話概括volatile,它能夠使變量在值發生改變時能儘快地讓其他線程知道。

3、volatile詳解

  首先我們要先意識到有這樣的現象,編譯器爲了加快程序運行的速度,對一些變量的寫操作會先在寄存器或者是CPU緩存上進行,最後才寫入內存.
而在這個過程中,變量的新值對其他線程是不可見的.

  當對volatile標記的變量進行修改時,會將其他緩存中存儲的修改前的變量清除,然後重新讀取。這裏從哪讀取我並不明確,一般來說應該是先在進行修改的緩存A中修改爲新值,然後通知其他緩存清除掉此變量,當其他緩存B中的線程讀取此變量時,會向總線發送消息,這時存儲新值的緩存A獲取到消息,將新值穿給B。最後將新值寫入內存。當變量需要更新時都是此步驟,volatile的作用是被其修飾的變量,每次更新時,都會刷新上述步驟。

4、volatile與synchronized

1)volatile本質是在告訴jvm當前變量在寄存器中的值是不確定的,需要從主存中讀取,synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住.
2)volatile僅能使用在變量級別,synchronized則可以使用在變量,方法.
3)volatile僅能實現變量的修改可見性,而synchronized則可以保證變量的修改可見性和原子性.

  《Java編程思想》上說,定義long或double變量時,如果使用volatile關鍵字,就會獲得(簡單的賦值與返回操作)原子性
4)volatile不會造成線程的阻塞,而synchronized可能會造成線程的阻塞.

5、當一個域的值依賴於它之前的值時,volatile就無法工作了,如n=n+1,n++等。如果某個域的值受到其他域的值的限制,那麼volatile也無法工作,如Range類的lower和upper邊界,必須遵循lower<=upper的限制。

6、使用volatile而不是synchronized的唯一安全的情況是類中只有一個可變的域。

發佈了32 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章