synchronized底層如何實(shí)現(xiàn)?什么是鎖的升級(jí)、降級(jí)?
synchronized代碼塊是由一對(duì)兒monitorenter/monitorexit指令實(shí)現(xiàn)的击吱, Monitor對(duì)象是同步的基本實(shí)現(xiàn)單元。
在Java 6之前遥昧, Monitor的實(shí)現(xiàn)完全是依靠操作系統(tǒng)內(nèi)部的互斥鎖覆醇,因?yàn)樾枰M(jìn)行用戶態(tài)到內(nèi)核態(tài)的切換,所以同步操作是一個(gè)無(wú)差別的重量級(jí)操作炭臭。
現(xiàn)代的(Oracle) JDK6中永脓, JVM對(duì)此進(jìn)行了大刀闊斧地改進(jìn),提供了三種不同的Monitor實(shí)現(xiàn)鞋仍,也就是常說(shuō)的三種不同的鎖:偏斜鎖(Biased Locking)常摧、輕量級(jí)鎖和重量級(jí)鎖,大大改進(jìn)了其性能威创。
鎖的升級(jí)落午、降級(jí),就是JVM優(yōu)化synchronized運(yùn)行的機(jī)制肚豺,當(dāng)JVM檢測(cè)到不同的競(jìng)爭(zhēng)狀況時(shí)溃斋,會(huì)自動(dòng)切換到適合的鎖實(shí)現(xiàn),這種切換就是鎖的升級(jí)吸申、降級(jí)梗劫。
偏向鎖
引入偏向鎖的目的:在沒(méi)有多線程競(jìng)爭(zhēng)的情況下,盡量減少不必要的輕量級(jí)鎖執(zhí)行路徑截碴,輕量級(jí)鎖的獲取及釋放依賴(lài)多次CAS原子指令在跳,而偏向鎖只依賴(lài)一次CAS原子指令置換ThreadID,不過(guò)一旦出現(xiàn)多個(gè)線程競(jìng)爭(zhēng)時(shí)必須撤銷(xiāo)偏向鎖隐岛,所以撤銷(xiāo)偏向鎖消耗的性能必須小于之前節(jié)省下來(lái)的CAS原子操作的性能消耗,不然就得不償失了瓷翻。JDK 1.6中默認(rèn)開(kāi)啟偏向鎖聚凹,可以通過(guò)-XX:-UseBiasedLocking來(lái)禁用偏向鎖。
偏向鎖的撤銷(xiāo)
只有當(dāng)其它線程嘗試競(jìng)爭(zhēng)偏向鎖時(shí)齐帚,持有偏向鎖的線程才會(huì)釋放鎖妒牙,偏向鎖的撤銷(xiāo)由BiasedLocking::revoke_at_safepoint方法實(shí)現(xiàn):
輕量級(jí)鎖
引入輕量級(jí)鎖的目的:在多線程交替執(zhí)行同步塊的情況下,盡量避免重量級(jí)鎖引起的性能消耗对妄,但是如果多個(gè)線程在同一時(shí)刻進(jìn)入臨界區(qū)湘今,會(huì)導(dǎo)致輕量級(jí)鎖膨脹升級(jí)重量級(jí)鎖,所以輕量級(jí)鎖的出現(xiàn)并非是要替代重量級(jí)鎖剪菱。
重量級(jí)鎖
重量級(jí)鎖通過(guò)對(duì)象內(nèi)部的監(jiān)視器(monitor)實(shí)現(xiàn)摩瞎,其中monitor的本質(zhì)是依賴(lài)于底層操作系統(tǒng)的Mutex Lock實(shí)現(xiàn)拴签,操作系統(tǒng)實(shí)現(xiàn)線程之間的切換需要從用戶態(tài)到內(nèi)核態(tài)的切換,切換成本非常高旗们。
java對(duì)象頭實(shí)現(xiàn)
HotSpot虛擬機(jī)中蚓哩,對(duì)象在內(nèi)存中的布局分為三塊區(qū)域:對(duì)象頭、實(shí)例數(shù)據(jù)和對(duì)齊填充上渴。
對(duì)象頭
對(duì)象頭包括兩部分:Mark Word 和 類(lèi)型指針岸梨。
Mark Word
Mark Word用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)稠氮、GC分代年齡曹阔、鎖狀態(tài)標(biāo)志、線程持有的鎖隔披、偏向線程ID赃份、偏向時(shí)間戳等等,占用內(nèi)存大小與虛擬機(jī)位長(zhǎng)一致锹锰。
類(lèi)型指針
類(lèi)型指針指向?qū)ο蟮念?lèi)元數(shù)據(jù)芥炭,虛擬機(jī)通過(guò)這個(gè)指針確定該對(duì)象是哪個(gè)類(lèi)的實(shí)例。
hash: 保存對(duì)象的哈希碼
age: 保存對(duì)象的分代年齡
biased_lock: 偏向鎖標(biāo)識(shí)位
lock: 鎖狀態(tài)標(biāo)識(shí)位
JavaThread:* 保存持有偏向鎖的線程ID
epoch: 保存偏向時(shí)間戳
參考文獻(xiàn):
JVM源碼分析之synchronized實(shí)現(xiàn)
JVM源碼分析之java對(duì)象頭實(shí)現(xiàn)