Java記憶體模型FAQ(八)Final欄位如何改變它們的值

喝水會長肉發表於2021-12-02

我們可以通過分析String類的實現具體細節來展示一個final變數是如何可以改變的。

String物件包含了三個欄位:一個character陣列,一個陣列的offset和一個length。實現String類的基本原理為:它不僅僅擁有character陣列,而且為了避免多餘的物件分配和拷貝,多個String和StringBuffer物件都會共享相同的character陣列。因此,String.substring()方法能夠通過改變length和offset,而共享原始的character陣列來建立一個新的String。對一個String來說,這些欄位都是final型的欄位。

String s1 
= 
"/usr/tmp"
; 

String s2 = s1 . substring ( 4 ) ;

字串s2的offset的值為4,length的值為4。但是,在舊的記憶體模型下,對其他執行緒來說,看到offset擁有預設的值0是可能的,而且,稍後一點時間會看到正確的值4,好像字串的值從“/usr”變成了“/tmp”一樣。

舊的Java記憶體模型允許這些行為,部分JVM已經展現出這樣的行為了。在新的Java記憶體模型裡面,這些是非法的。


原文

How can final fields appear to change their values?

One of the best examples of how final fields’ values can be seen to change involves one particular implementation of the String class.

A String can be implemented as an object with three fields — a character array, an offset into that array, and a length. The rationale for implementing String this way, instead of having only the character array, is that it lets multiple String and StringBufferobjects share the same character array and avoid additional object allocation and copying. So, for example, the method String.substring() can be implemented by creating a new string which shares the same character array with the original String and merely differs in the length and offset fields. For a String, these fields are all final fields.


//java學習交流:737251827  進入可領取學習資源及對十年開發經驗大佬提問,免費解答!

String s1 = "/usr/tmp" ;
String s2 = s1 . substring ( 4 ) ;

The string s2 will have an offset of 4 and a length of 4. But, under the old model, it was possible for another thread to see the offset as having the default value of 0, and then later see the correct value of 4, it will appear as if the string “/usr” changes to “/tmp”.

The original Java Memory Model allowed this behavior; several JVMs have exhibited this behavior. The new Java Memory Model makes this illegal.



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010294/viewspace-2845402/,如需轉載,請註明出處,否則將追究法律責任。

相關文章