volatile與synchronized的區別

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

  互斥即一次只容許一個線程持有某個特定的鎖,所以可以使用該特性實現對共享數據的協調訪問協議,這樣,一次就只有一個線程可以使用該共享數據。緩存

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

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

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

  使用volatile關鍵字:用一句話歸納volatile,它可以使變量在值發生改變時能儘快地讓其餘線程知道。線程

三、volatile詳解對象

 當一個變量定義爲volatile後,它將具有兩種特性:1. 可見性,2. 禁止指令重排序。排序

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

    可見性:當對volatile標記的變量進行修改時,會將其它緩存中存儲的修改前的變量清除,而後從新讀取。這裏從哪讀還沒有明確,通常來講應該是先在進行修改的緩存A中修改成新值,而後通知其它緩存清除掉此變量,當其它緩存B中的線程讀取此變量時,會向總線發送消息,這是存儲新值的緩存A獲取到消息,將新值傳給B,最後將新值寫入內存。編譯器

 

volatile的做用是被其修飾的變量每次刷新時,都會刷新上述步驟。

四、volatile與synchronized

   1)volatile本質是告訴JVM當前變量在寄存器中的值是不肯定的,須要從主存中讀取。synchronized則是鎖定當前變量,只有當前線程能夠訪問該變量,其它線程被阻塞。

   2)volatile僅能使用在變量級別,synchronized則可使用在變量、方法

   3)volatile僅能實現變量修改的可見性,而synchronized則能夠保證變量修改的可見性和原子性《Java編程思想》上說,定義long或double時,若是使用volatile關鍵字(簡單的賦值與返回操做),就會得到原子性。(常規狀態下,這兩個變量因爲其長度,其操做不是原子的)

   4)volatile不會形成線程阻塞,synchronized形成線程阻塞。

   5)使用volatile而不是synchronized的惟一安全狀況是類中只有一個可變的域

五、當一個域的值依賴於它以前的值時,volatile就沒法工做了,如n=n+1,n++等。若是某個域的值受到其餘域的值的限制,那麼volatile也沒法工做,如Range類的lower和upper邊界,必須遵循lower<=upper的限制。

六、使用volatile而不是synchronized的惟一安全的狀況是類中只有一個可變的域。

相關文章
相關標籤/搜索