在程序設計中,尤爲是在C語言、C++、C#和Java語言中,使用volatile關鍵字聲明的變量或對象一般擁有和優化和(或)多線程相關的特殊屬性。一般,volatile關鍵字用來阻止(僞)編譯器對那些它認爲變量的值不能「被代碼自己」改變的代碼上執行任何優化。 在C環境中,volatile關鍵字的真實定義和適用範圍常常被誤解,加之C++、C#和Java都從C中神祕地「繼承」了volatile,在這些編程語言中,所以這些語言中volatile的用法和語義截然不同。編程
Java也支持volatile關鍵字,但它被用於其餘不一樣的用途。當volatile用於一個做用域時,Java保證以下:緩存
1.(適用於Java全部版本)讀和寫一個volatile變量有全局的排序。也就是說每一個線程訪問一個volatile做用域時會在繼續執行以前讀取它的當前值,而不是(可能)使用一個緩存的值,直接從主存中讀取,避免編譯器優化。(可是並不保證常常讀寫volatile做用域時讀和寫的相對順序,也就是說一般這並非有用的線程構建)。多線程
2.(適用於Java5及其以後的版本)volatile的讀和寫創建了一個happens-before關係,相似於申請和釋放一個互斥鎖。併發
這時,聯想到的另外一個關鍵詞即是synchronized.可用來給對象和方法或者代碼塊加鎖,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多隻有一個線程執行這個段代碼。當兩個併發線程訪問同一個對象object中的這個加鎖同步代碼塊時,一個時間內只能有一個線程獲得執行。另外一個線程必須等待當前線程執行完這個代碼塊之後才能執行該代碼塊。然而,當一個線程訪問object的一個加鎖代碼塊時,另外一個線程仍然能夠訪問該object中的非加鎖代碼塊。app
所以,兩個關鍵詞的區別以下:jvm
1.volatile本質是在告訴jvm當前變量在寄存器(工做內存)中的值是不肯定的,須要從主存中讀取;synchronized則是鎖定當前變量,只有當前線程能夠訪問該變量,其餘線程被阻塞住。編程語言
2.volatile僅能使用在變量級別;synchronized則可使用在變量、方法、和類級別的。優化
3.volatile僅能實現變量的修改可見性,並能保證原子性;而synchronized則能夠保證變量的修改可見性和原子性。spa
4.volatile不會形成線程的阻塞;synchronized可能會形成線程的阻塞。 線程
5.volatile標記的變量不會被編譯器優化;synchronized標記的變量能夠被編譯器優化。