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中必要的代碼優化,所以在效率上比較低,因此一定在必要時才使用此關鍵字。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章