1. 程式人生 > >java中的關鍵字:transient和volatile

java中的關鍵字:transient和volatile

Java定義了兩類有趣的修飾符:transient和volatile

 1、    transient此為java保留字,告訴JVM以transient宣告的基本型態(primitive type)或物件(object)變數不要序列化,例如敏感性的資料像密碼等。 

   如果用transient宣告一個例項變數,當物件儲存時,它的值不需要維持。例如:

   class Test {
            transient int a; // 不會被持久化
           int b; // 持久化
   }  

 當類Test的例項物件被序列化(比如將Test類的例項物件 t 寫入硬碟的文字檔案t.txt中),變數 a 的內容不會被儲存,變數 b 的內容則會被儲存。

2、volatile用更低的代價替代同步(synchronized)。

    為什麼使用volatile比同步代價更低?

    同步的代價,主要由其覆蓋範圍決定,如果可以降低同步的覆蓋範圍,則可以大幅提升程式效能。而volatile的覆蓋範圍僅僅變數級別的,因此它的同步代價很低。

   volatile的工作原理:

volatile的語義,其實是告訴處理器,不要將我放入工作記憶體,請直接在主存操作我。因此,當多核或多執行緒在訪問該變數時,都將直接操作主存,這從本質上,做到了變數共享。

參考:
把一個物件的表示轉化為位元組流的過程稱為序列化(也稱為序列化,serialization),從位元組流中把物件

重建出來稱為反序列化(也稱為為反序列化,deserialization)。transient 為不應被序列化的資料提供了一個語言級的標記資料方法。

volatile
volatile也是變數修飾符,只能用來修飾變數。volatile修飾的成員變數在每次被執行緒訪問時,都強迫從共享記憶體中重讀該成員變數的值。而且,當成員變數發生變化時,強迫執行緒將變化值回寫到共享記憶體。這樣在任何時刻,兩個不同的執行緒總是看到某個成員變數的同一個值。

在此解釋一下Java的記憶體機制:

Java使用一個主記憶體來儲存變數當前值,而每個執行緒則有其獨立的工作記憶體。執行緒訪問變數的時候會將變數的值拷貝到自己的工作記憶體中,這樣,當執行緒對自己工作記憶體中的變數進行操作之後,就造成了工作記憶體中的變數拷貝的值與主記憶體中的變數值不同。

Java語言規範中指出:為了獲得最佳速度,允許執行緒儲存共享成員變數的私有拷貝,而且只當執行緒進入或者離開同步程式碼塊時才與共享成員變數的原始值對比。

這樣當多個執行緒同時與某個物件互動時,就必須要注意到要讓執行緒及時的得到共享成員變數的變化。

而volatile關鍵字就是提示VM:對於這個成員變數不能儲存它的私有拷貝,而應直接與共享成員變數互動。

使用建議:在兩個或者更多的執行緒訪問的成員變數上使用volatile。當要訪問的變數已在synchronized程式碼塊中,或者為常量時,不必使用。

由於使用volatile遮蔽掉了VM中必要的程式碼優化,所以在效率上比較低,因此一定在必要時才使用此關鍵字。