原文:
https://www.cnblogs.com/qqzy168/p/3658735.html
https://www.cnblogs.com/widow/p/3952827.html
transient和volatile兩個關鍵字一個用于對象序列化,一個用于線程同步,都是Java中比較高階的話題,簡單總結一下。
transient
transient是類型修飾符,只能用來修飾字段。在對象序列化的過程中,標記為transient的變量不會被序列化。
當類Test的實例對象被序列化(比如將Test類的實例對象 t 寫入硬盤的文本文件t.txt中),變量 a 的內(nèi)容不會被保存,變量 b 的內(nèi)容則會被保存。
參考:
把一個對象的表示轉化為字節(jié)流的過程稱為串行化(也稱為序列化,serialization),從字節(jié)流中把對象重建出來稱為反串行化(也稱為為反序列化,deserialization)。transient 為不應被串行化的數(shù)據(jù)提供了一個語言級的標記數(shù)據(jù)方法。
volatile
volatile 也是變量修飾符,只能用來修飾變量。volatile修飾的成員變量在每次被線程訪問時,都強迫從共享內(nèi)存中重讀該成員變量的值。而且,當成員變量發(fā)生變 化時,強迫線程將變化值回寫到共享內(nèi)存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。
作用:讓變量每次在使用的時候,都從主存中取,而不是從各個線程的“工作內(nèi)存”。
也就是說,volatile變量對于每次使用,線程都能得到當前volatile變量的最新值.
什么是線程的working memory
線程的working memory是cpu的寄存器和高速緩存的抽象描述:現(xiàn)在的計算機,cpu在計算的時候,并不總是從內(nèi)存讀取數(shù)據(jù),它的數(shù)據(jù)讀取順序優(yōu)先級 是:寄存器-高速緩存-內(nèi)存。
線程耗費的是CPU,線程計算的時候,原始的數(shù)據(jù)來自內(nèi)存,在計算過程中,有些數(shù)據(jù)可能被頻繁讀取,這些數(shù)據(jù)被存儲在寄存器和高速緩存中,當線程計算完后,這些緩存的數(shù)據(jù)在適當?shù)臅r候應該寫回內(nèi)存。當多個線程同時讀寫某個內(nèi)存數(shù)據(jù)時,就會產(chǎn)生多線程并發(fā)問題,涉及到三個特 性:原子性,有序性,可見性。 支持多線程的平臺都會面臨 這種問題,運行在多線程平臺上支持多線程的語言應該提供解決該問題的方案。
簡而言之:每個線程都有自己的執(zhí)行空間(即工作內(nèi)存),線程執(zhí)行的時候用到某變量,首先要將變量從主內(nèi)存拷貝的自己的工作內(nèi)存空間,然后對變量進行操作:讀取,修改,賦值等,這些均在工作內(nèi)存完成,操作完成后再將變量寫回主內(nèi)存;
再來解釋一下Java的內(nèi)存機制:
Java使用一個主內(nèi)存來保存變量當前值,而每個線程則有其獨立的工作內(nèi)存。線程訪問變量的時候會將變量的值拷貝到自己的工作內(nèi)存中,這樣,當線程對自己工作內(nèi)存中的變量進行操作之后,就造成了工作內(nèi)存中的變量拷貝的值與主內(nèi)存中的變量值不同。
Java語言規(guī)范中指出:為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變量的原始值對比。
這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變量的變化。
而volatile關鍵字就是提示VM:對于這個成員變量不能保存它的私有拷貝,而應直接與共享成員變量交互。
使用建議:在兩個或者更多的線程訪問的成員變量上使用volatile。當要訪問的變量已在synchronized代碼塊中,或者為常量時,不必使用。
由于使用volatile屏蔽掉了VM中必要的代碼優(yōu)化,所以在效率上比較低,因此一定在必要時才使用此關鍵字。
補充:
volatile 和 synchronized區(qū)別
volatile具有synchronized關鍵字的“可見性”,但是沒有synchronized關鍵字的“并發(fā)正確性”,也就是說不保證線程執(zhí)行的有序性。
也就是說,volatile變量對于每次使用,線程都能得到當前volatile變量的最新值。但是volatile變量并不保證并發(fā)的正確性。
1.volatile本質(zhì)是在告訴jvm當前變量在寄存器(工作內(nèi)存)中的值是不確定的,需要從主存中讀?。?synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
2.volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
3.volatile僅能實現(xiàn)變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性
4.volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
5.volatile標記的變量不會被編譯器優(yōu)化;synchronized標記的變量可以被編譯器優(yōu)化
總結: synchronized: 具有原子性,有序性和可見性;
volatile:具有有序性和可見性