java中transient、volatile、strictfp關鍵字說明


1、transient,用於對象序列化。

transient是類型修飾符,只能用來修飾字段。在對象序列化的過程中,標記爲transient的變量不會被序列化。

示例:

class Test {

transient int a; // 不會被持久化

int b; // 持久化

}

當類Test的實例對象被序列化(比如將Test類的實例對象 t 寫入硬盤的文本文件t.txt中),變量 a 的內容不會被保存,變量 b 的內容則會被保存。

參考:
把一個對象的表示轉化爲字節流的過程稱爲串行化(也稱爲序列化,serialization),從字節流中把對象重建出來稱爲反串行化(也稱爲爲反序列化,deserialization)。transient 爲不應被串行化的數據提供了一個語言級的標記數據方法。


2、volatile,用於線程同步

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

在此解釋一下Java的內存機制:

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

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

這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變量的變化。

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

使用建議:在兩個或者更多的線程訪問的成員變量上使用volatile。當要訪問的變量已在synchronized代碼塊中,或者爲常量時,不必使用。

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


3、strictfp,用於浮點運算

用strictfp修飾類或方法,可以確保浮點運算(以及所有切斷)正如早期的Java版本那樣準確。切斷隻影響某些操作的指數。當一個類被strictfp修飾,所有的方法自動被strictfp修飾。 
    strictfp的意思是FP-strict,也就是說精確浮點的意思。在Java虛擬機進行浮點運算時,如果沒有指定strictfp關鍵字時,Java的編譯器以及運行環境在對浮點運算的表達式是採取一種近似於我行我素的行爲來完成這些操作,以致於得到的結果往往無法令你滿意。而一旦使用了strictfp來聲明一個類、接口或者方法時,那麼所聲明的範圍內Java的編譯器以及運行環境會完全依照浮點規範IEEE-754來執行。因此如果你想讓你的浮點運算更加精確,而且不會因爲不同的硬件平臺所執行的結果不一致的話,那就請用關鍵字strictfp。 
你可以將一個類、接口以及方法聲明爲strictfp,但是不允許對接口中的方法以及構造函數聲明strictfp關鍵字,例如下面的代碼: 

1. 合法的使用關鍵字strictfp 

Java代碼  收藏代碼
  1. strictfp interface A {}  
  2.   
  3. public strictfp class FpDemo1 {  
  4.     strictfp void f() {}  
  5. }  

2. 錯誤的使用方法 
Java代碼  收藏代碼
  1. interface A {  
  2.     strictfp void f();  
  3. }  
  4.   
  5. public class FpDemo2 {  
  6.     strictfp FpDemo2() {}  
  7. }  

一旦使用了關鍵字strictfp來聲明某個類、接口或者方法時,那麼在這個關鍵字所聲明的範圍內所有浮點運算都是精確的,符合IEEE-754規範的。例如一個類被聲明爲strictfp,那麼該類中所有的方法都是strictfp的。 


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