JDK 的原始碼你真的讀懂了嗎?
如果看過JDK原始碼的同學基本上都看到過類似於下面的語句:
對“final ReentrantLock lock = this.lock; ”這種寫法不知道大家是啥感受,我當時看到是非常奇怪的,於是就搜尋了一下,發現原作者對這種情況做了說明,原文如下:
其中第一句就提到了這樣做的原因是:“ 歸根究底是由於記憶體模型與OOP之間的原則不一致 ”,後面基本上都是對這句話做出說明。
要理解上面的內容必須要對Java的記憶體模型有所瞭解,Java的記憶體模型如下:
從上圖我們可以知道Thread Stack 是以過程函式為訪問物件,而不是以物件問訪問的,執行緒棧內只有基本變數和指向物件的引用(物件本身是放在heap上)。
從java記憶體模型中可以看出,method只會存放物件引用(this指標),不會存放物件中的資訊,只能再次通過this訪問物件中的資訊。
所以這種寫法,在訪問lock的時候首先去訪問this物件,然後獲取lock的引用,最後再呼叫lock函式,每次訪問lock中的函式都是這3步。
但是如果採用將欄位賦值給區域性變數在使用,之後就不需要訪問this指標,少了一步操作. 也就是說this物件和其他普通物件在函式沒有任何區別
為了驗證,可以對程式碼進行反編譯:
反編譯的結果和記憶體模型推斷出來的完全一致。 雖然採用將欄位賦值給區域性變數在以後使用中確實能夠節省時間,但是目前的JDK版本對於這種情況下都做了優化。所以這種寫法已經變成了 Doug Lea習慣了。