java transient 和Volatile关键字
Volatile修飾的成員變量在每次被線程訪問時(shí),都強(qiáng)迫從主內(nèi)存中重讀該成員變量的值。而且,當(dāng)成員變量發(fā)生變化時(shí),強(qiáng)迫線程將變化值回寫到主內(nèi)存。這樣在任何時(shí)刻,兩個(gè)不同的線程總是看到某個(gè)成員變量的同一個(gè)值。???
??
Java語言規(guī)范中指出:為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當(dāng)線程進(jìn)入或者離開同步代碼塊時(shí)才與共享成員變量的原始值對(duì)比。???
??
這樣當(dāng)多個(gè)線程同時(shí)與某個(gè)對(duì)象交互時(shí),就必須要注意到要讓線程及時(shí)的得到共享成員變量的變化。???
??
而volatile關(guān)鍵字就是提示VM:對(duì)于這個(gè)成員變量不能保存它的私有拷貝,而應(yīng)直接與共享成員變量交互。???
??
使用建議:在兩個(gè)或者更多的線程訪問的成員變量上使用volatile。當(dāng)要訪問的變量已在synchronized代碼塊中,或者為常量時(shí),不必使用。???
??
由于使用volatile屏蔽掉了VM中必要的代碼優(yōu)化,所以在效率上比較低,因此一定在必要時(shí)才使用此關(guān)鍵字。???
??
java關(guān)鍵字Transient???
??
轉(zhuǎn)自http://horst.sun.blog.163.com/blog/static/348849612007614494492/???
??
翻譯自http://www.devx.com/tips/Tip/13726。???
??
Java的serialization提供了一種持久化對(duì)象實(shí)例的機(jī)制。當(dāng)持久化對(duì)象時(shí),可能有一個(gè)特殊的對(duì)象數(shù)據(jù)成員,我們不想???
用serialization機(jī)制來保存它。為了在一個(gè)特定對(duì)象的一個(gè)域上關(guān)閉serialization,可以在這個(gè)域前加上關(guān)鍵字transient。???
transient是Java語言的關(guān)鍵字,用來表示一個(gè)域不是該對(duì)象串行化的一部分。當(dāng)一個(gè)對(duì)象被串行化的時(shí)候,transient型變量的值不包括在串行化的表示中,然而非transient型的變量是被包括進(jìn)去的。??
注意static變量也是可以串行化的?
??
首先,讓我們看一些Java?serialization的代碼:???
public?class?LoggingInfo?implements?java.io.Serializable???
{???
????private?Date?loggingDate?=?new?Date();???
????private?String?uid;???
????private?transient?String?pwd;???
??????
????LoggingInfo(String?user,?String?password)???
????{???
????????uid?=?user;???
????????pwd?=?password;???
????}???
????public?String?toString()???
????{???
????????String?password=null;???
????????if(pwd?==?null)???
????????{???
????????password?=?"NOT?SET";???
????????}???
????????else??
????????{???
????????????password?=?pwd;???
????????}???
????????return?"logon?info:?\n???"?+?"user:?"?+?uid?+???
????????????"\n???logging?date?:?"?+?loggingDate.toString()?+???
????????????"\n???password:?"?+?password;???
????}???
}???
??
現(xiàn)在我們創(chuàng)建一個(gè)這個(gè)類的實(shí)例,并且串行化(serialize)它?,然后將這個(gè)串行化對(duì)象寫如磁盤。???
??
LoggingInfo?logInfo?=?new?LoggingInfo("MIKE",?"MECHANICS");???
System.out.println(logInfo.toString());???
try??
{???
???ObjectOutputStream?o?=?new?ObjectOutputStream(???
????????????????new?FileOutputStream("logInfo.out"));???
???o.writeObject(logInfo);???
???o.close();???
}???
catch(Exception?e)?{//deal?with?exception}???
??
To?read?the?object?back,?we?can?write???
??
try??
{???
???ObjectInputStream?in?=new?ObjectInputStream(???
????????????????new?FileInputStream("logInfo.out"));???
???LoggingInfo?logInfo?=?(LoggingInfo)in.readObject();???
???System.out.println(logInfo.toString());???
}???
catch(Exception?e)?{//deal?with?exception}???
??
如果我們運(yùn)行這段代碼,我們會(huì)注意到從磁盤中讀回(read——back?(de-serializing))的對(duì)象打印password為"NOT?SET"。這是當(dāng)我們定義pwd域?yàn)閠ransient時(shí),所期望的正確結(jié)果。???
現(xiàn)在,讓我們來看一下粗心對(duì)待transient域可能引起的潛在問題。假設(shè)我們修改了類定義,提供給transient域一個(gè)默認(rèn)值,???
代碼如下:???
??
public?class?GuestLoggingInfo?implements?java.io.Serializable???
{???
????private?Date?loggingDate?=?new?Date();???
????private?String?uid;???
????private?transient?String?pwd;???
??????
????GuestLoggingInfo()???
????{???
????????uid?=?"guest";???
????????pwd?=?"guest";???
????}???
????public?String?toString()???
????{???
????????//same?as?above???
?????}???
}???
現(xiàn)在,如果我們穿行化GuestLoggingInfo的一個(gè)實(shí)例,將它寫入磁盤,并且再將它從磁盤中讀出,我們?nèi)匀豢吹阶x回的對(duì)象打印password?為?"NOT?SET"。當(dāng)從磁盤中讀出某個(gè)類的實(shí)例時(shí),實(shí)際上并不會(huì)執(zhí)行這個(gè)類的構(gòu)造函數(shù),???
而是載入了一個(gè)該類對(duì)象的持久化狀態(tài),并將這個(gè)狀態(tài)賦值給該類的另一個(gè)對(duì)象。??
轉(zhuǎn)載于:https://www.cnblogs.com/crhdyl/p/4929203.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的java transient 和Volatile关键字的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Codeforces 362E Pety
- 下一篇: [转载]WSUS客户端排错--使用wsu