Java面試synchronized偏向鎖后hashcode存址
前言
今天的文章從下面這張圖片開始,這張圖片Java開發(fā)們應(yīng)該很熟悉了
我們都知道無(wú)鎖狀態(tài)是對(duì)象頭是有位置存儲(chǔ)hashcode的,而變?yōu)槠蜴i狀態(tài)是沒(méi)有位置存儲(chǔ)hashcode的,今天我們來(lái)通過(guò)實(shí)現(xiàn)驗(yàn)證這個(gè)問(wèn)題:當(dāng)鎖狀態(tài)為偏向鎖的時(shí)候,hashcode存到哪里去了?
先說(shuō)結(jié)論:
- jdk8偏向鎖是默認(rèn)開啟,但是是有延時(shí)的
可通過(guò)參數(shù): -XX:BiasedLockingStartupDelay=0關(guān)閉延時(shí)。 - hashcode是懶加載,在調(diào)用hashCode方法后才會(huì)保存在對(duì)象頭中。
- 當(dāng)對(duì)象頭中沒(méi)有hashcode時(shí),對(duì)象頭鎖的狀態(tài)是 可偏向( biasable,101,且無(wú)線程id)。
- 如果在同步代碼塊之前調(diào)用hashCode方法,則對(duì)象頭中會(huì)有hashcode,且鎖狀態(tài)是 不可偏向(0 01),這時(shí)候再執(zhí)行同步代碼塊,鎖直接是 輕量級(jí)鎖(thin lock,00)。
如果是在同步代碼塊中執(zhí)行hashcode,則鎖是從 偏向鎖 直接膨脹為 重量級(jí)鎖。
1、hashcode是啥時(shí)候存進(jìn)對(duì)象頭中?
根據(jù)下圖我們可知,hashcode并不是對(duì)象實(shí)例化后就創(chuàng)建,而是在調(diào)用默認(rèn)的hasCode方法時(shí)才會(huì)放進(jìn)對(duì)象頭。
第一次打印的對(duì)象頭中我們發(fā)現(xiàn)對(duì)象頭中mark word值為16進(jìn)制的5,轉(zhuǎn)為2進(jìn)制就是101,且后面的狀態(tài)顯示為biasable,也就是可偏向,注意區(qū)分可偏向和已偏向:可偏向表示還么有synchronized鎖,已偏向表示有線程訪問(wèn)鎖。
第二次打印對(duì)象頭中已經(jīng)存在hashcode,value為0x00000039a054a501,轉(zhuǎn)換為2進(jìn)制為:11100110100000010101001010010100000001,最后三位也就是0 01,這就表示不可偏向,也就說(shuō)當(dāng)出現(xiàn)synchronized鎖不會(huì)進(jìn)行偏向,真是如此嗎?我們驗(yàn)證一下!
2、存在hashcode后,出現(xiàn)synchronized會(huì)是什么鎖?
根據(jù)下圖我們可以清晰的看到,當(dāng)已存在hashcode再執(zhí)行同步代碼,則會(huì)直接進(jìn)入輕量級(jí)鎖,原因還是上面的結(jié)論,有hashcode后將鎖設(shè)置為 不可偏向,那肯定就直接上輕量級(jí)鎖咯。
3、如果鎖狀態(tài)是 已偏向,再計(jì)算hashcode會(huì)怎樣?
前面兩種情況鎖狀態(tài)都是 可偏向 狀態(tài),如果此時(shí)鎖狀態(tài)是 已經(jīng)進(jìn)入偏向狀態(tài)呢?是會(huì)進(jìn)行鎖升級(jí)嘛?
根據(jù)下圖我們可以看到,當(dāng)hashCode方法處于synchronized代碼塊中時(shí),鎖直接升級(jí)為重量級(jí)鎖。
至于為什么直接升級(jí)為重量級(jí)鎖而不是輕量級(jí)鎖,這個(gè)原因不得而知。
豬哥猜想可能無(wú)線程競(jìng)爭(zhēng)狀態(tài)下,偏向鎖升級(jí)為重量級(jí)鎖消耗的資源比輕量級(jí)鎖消耗的資源少。
同時(shí)歡迎知道原因的同學(xué)能夠留言告知,也歡迎大家說(shuō)出自己的猜想?沒(méi)準(zhǔn)以后會(huì)根據(jù)你的方案優(yōu)化呢!
4、總結(jié)
- jdk8偏向鎖是默認(rèn)開啟,但是是有延時(shí)的,可通過(guò)參數(shù): -XX:BiasedLockingStartupDelay=0關(guān)閉延時(shí)。
- hashcode是懶加載,在調(diào)用hashCode方法后才會(huì)保存在對(duì)象頭中。
- 當(dāng)對(duì)象頭中沒(méi)有hashcode時(shí),對(duì)象頭鎖的狀態(tài)是 可偏向( biasable,101,且無(wú)線程id)。
- 如果在同步代碼塊之前調(diào)用hashCode方法,則對(duì)象頭中會(huì)有hashcode,且鎖狀態(tài)是 不可偏向(0 01),這時(shí)候再執(zhí)行同步代碼塊,鎖直接是 輕量級(jí)鎖(thin lock,00)。
- 如果是在同步代碼塊中執(zhí)行hashcode,則鎖是從 偏向鎖 直接膨脹為 重量級(jí)鎖。
以上就是Java面試synchronized偏向鎖后hashcode存址的詳細(xì)內(nèi)容,更多關(guān)于java 偏向鎖hashcode存址的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
我勸你謹(jǐn)慎使用Spring中的@Scheduled注解
這篇文章主要介紹了Spring中的@Scheduled注解使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10SpringBoot加載配置文件的實(shí)現(xiàn)方式總結(jié)
在實(shí)際的項(xiàng)目開發(fā)過(guò)程中,我們經(jīng)常需要將某些變量從代碼里面抽離出來(lái),放在配置文件里面,以便更加統(tǒng)一、靈活的管理服務(wù)配置信息。所以本文將為大家總結(jié)一下SpringBoot加載配置文件的常用方式,需要的可以參考一下2022-03-03springboot服務(wù)正常啟動(dòng)之后,訪問(wèn)服務(wù)url無(wú)響應(yīng)問(wèn)題及解決
這篇文章主要介紹了springboot服務(wù)正常啟動(dòng)之后,訪問(wèn)服務(wù)url無(wú)響應(yīng)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Mybatis?Mapper中多參數(shù)方法不使用@param注解報(bào)錯(cuò)的解決
這篇文章主要介紹了Mybatis?Mapper中多參數(shù)方法不使用@param注解報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。2022-01-01springboot?aop配合反射統(tǒng)一簽名驗(yàn)證實(shí)踐
這篇文章主要介紹了springboot?aop配合反射統(tǒng)一簽名驗(yàn)證實(shí)踐,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12elasticsearch構(gòu)造Client實(shí)現(xiàn)java客戶端調(diào)用接口示例分析
這篇文章主要為大家介紹了elasticsearch構(gòu)造Client實(shí)現(xiàn)java客戶端調(diào)用接口示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04mybatis Plus 多表聯(lián)合查詢的實(shí)現(xiàn)示例
這篇文章主要介紹了mybatis Plus 多表聯(lián)合查詢的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09