基于jdk8u源碼梳理,超詳細synchronized粗化流程圖及總結(jié)

上一次我們說了偏向鎖的一些場景,但省略了偏向鎖重定向、批量重定向、批量撤銷等有意思而又復雜的內(nèi)容(事實上,由于偏向鎖內(nèi)容確實復雜,jdk開發(fā)者在jdk15中已經(jīng)將其廢棄了,需要手動開啟)。同時關(guān)于其他的粗化狀態(tài)也并未提及。因此本文將基于jdk8u的c++源碼,來梳理整個流程。
考慮到本文較為硬核,在此之前,你可能需要一些基礎(chǔ)知識,首先還是上一張老圖

synchronized的膨脹基本遵循 匿名偏向? 》偏向鎖? 》輕量級鎖? 》重量級鎖的過程。
偏向鎖一旦被持有,即使持有的線程退出同步代碼塊。偏向鎖也不會撤銷或消失。此時若有第二個線程嘗試獲取鎖,將直接升級至輕量級鎖
上圖里有個epoch字段,這個字段意為“紀元”,是為了判斷當前偏向鎖是否有效而引入的。我們需要知道,如果有一個類名為ClassA,除了依據(jù)ClassA?new出來的實例對象外,ClassA本身也有個類對象,一般情況下,類對象的epoch是最新的,各實例對象的epoch和類對象的epoch保持一致,當某個實例對象發(fā)現(xiàn)自己的epoch落后了,代表它的偏向鎖失效,此時可以重新偏向其他線程。
重量級鎖與前面幾種鎖有本質(zhì)不同,涉及到線程的阻塞,它并非通過棧和棧上標記實現(xiàn),而是基于c++里的objectMonitor對象實現(xiàn),我們在java中看到Object類里的wait()、notify()等方法其實是objectMonitor的方法,因此調(diào)用這些方法時,無論對象原本是什么狀態(tài),都會直接進入重量級鎖狀態(tài)
更詳細的膨脹過程,和相關(guān)說明都在流程圖中,圖是基于jdk8u的c++源碼整理出來的,說是全網(wǎng)最全最細也不為過。圖中還編寫了一些總結(jié),希望能幫大家梳理通思路。至于重量級鎖后的鎖獲取分析,會在之后推出。
(聲明:因時間和本人水平限制,難免有所錯漏,如果發(fā)現(xiàn)問題,歡迎及時指正)
