【synchronized底层原理之4】锁的升级过程及比较
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
參考
https://blog.csdn.net/zqz_zqz/article/details/70233767
https://monkeysayhi.github.io/2018/01/02/%E6%B5%85%E8%B0%88%E5%81%8F%E5%90%91%E9%94%81%E3%80%81%E8%BD%BB%E9%87%8F%E7%BA%A7%E9%94%81%E3%80%81%E9%87%8D%E9%87%8F%E7%BA%A7%E9%94%81/
偏向鎖獲取過(guò)程
輕量級(jí)鎖的加鎖過(guò)程
輕量級(jí)鎖的釋放過(guò)程
釋放鎖線程的視角
由輕量鎖切換到重量鎖,是發(fā)生在輕量鎖釋放鎖的期間,之前在獲取鎖的時(shí)候它拷貝了鎖對(duì)象頭的markword,在釋放鎖的時(shí)候如果它發(fā)現(xiàn)在它持有鎖的期間有其他線程來(lái)嘗試獲取鎖了,并且該線程對(duì)markword做了修改,兩者比對(duì)發(fā)現(xiàn)不一致,則切換到重量鎖。
因?yàn)橹亓考?jí)鎖被修改了,所以display mark word和原來(lái)的markword不一樣了。
怎么補(bǔ)救,就是進(jìn)入mutex前,compare一下obj的markword狀態(tài)。確認(rèn)該markword是否被其他線程持有。
此時(shí)如果線程已經(jīng)釋放了markword,那么通過(guò)CAS后就可以直接進(jìn)入線程,無(wú)需進(jìn)入mutex,就這個(gè)作用。
嘗試獲取鎖線程的視角
如果線程嘗試獲取鎖的時(shí)候,輕量鎖正被其他線程占有,那么它就會(huì)修改markword,修改重量級(jí)鎖,表示該進(jìn)入重量鎖了。
還有一個(gè)注意點(diǎn):等待輕量鎖的線程不會(huì)阻塞,它會(huì)一直自旋等待鎖,并如上所說(shuō)修改markword。
這就是自旋鎖,嘗試獲取鎖的線程,在沒有獲得鎖的時(shí)候,不被掛起,而轉(zhuǎn)而去執(zhí)行一個(gè)空循環(huán),即自旋。在若干個(gè)自旋后,如果還沒有獲得鎖,則才被掛起(進(jìn)入阻塞狀態(tài)),獲得鎖,則執(zhí)行代碼。
synchronized的執(zhí)行過(guò)程
1. 檢測(cè)Mark Word里面是不是當(dāng)前線程的ID,如果是,表示當(dāng)前線程處于偏向鎖
2. 如果不是,則使用CAS將當(dāng)前線程的ID替換Mard Word,如果成功則表示當(dāng)前線程獲得偏向鎖,置偏向標(biāo)志位1
3. 如果失敗,則說(shuō)明發(fā)生競(jìng)爭(zhēng),撤銷偏向鎖,進(jìn)而升級(jí)為輕量級(jí)鎖。
4. 當(dāng)前線程使用CAS將對(duì)象頭的Mark Word替換為鎖記錄指針,如果成功,當(dāng)前線程獲得鎖
5. 如果失敗,表示其他線程競(jìng)爭(zhēng)鎖,當(dāng)前線程便嘗試使用自旋來(lái)獲取鎖。
6. 如果自旋成功則依然處于輕量級(jí)狀態(tài)。
7. 如果自旋失敗,則升級(jí)為重量級(jí)鎖。
上面幾種鎖都是JVM自己內(nèi)部實(shí)現(xiàn),當(dāng)執(zhí)行synchronized同步塊的時(shí)候jvm會(huì)根據(jù)啟用的鎖和當(dāng)前線程的爭(zhēng)用情況,決定如何執(zhí)行同步操作。
在所有的鎖都啟用的情況下線程進(jìn)入臨界區(qū)時(shí)會(huì)先去獲取偏向鎖,如果已經(jīng)存在偏向鎖了,則會(huì)嘗試獲取輕量級(jí)鎖,啟用自旋鎖,如果自旋也沒有獲取到鎖,則使用重量級(jí)鎖,沒有獲取到鎖的線程阻塞掛起,直到持有鎖的線程執(zhí)行完同步塊喚醒他們
偏向鎖是在無(wú)鎖爭(zhēng)用的情況下使用的,也就是同步開在當(dāng)前線程沒有執(zhí)行完之前,沒有其它線程會(huì)執(zhí)行該同步塊,一旦有了第二個(gè)線程的爭(zhēng)用,偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖,如果輕量級(jí)鎖自旋到達(dá)閾值后,沒有獲取到鎖,就會(huì)升級(jí)為重量級(jí)鎖。
如果線程爭(zhēng)用激烈,那么應(yīng)該禁用偏向鎖。
偏向鎖、輕量級(jí)鎖、重量級(jí)鎖的比較
| ? | 重量級(jí)鎖 | 輕量級(jí)鎖 | 偏向鎖 |
| 適用場(chǎng)景 | 發(fā)生了鎖爭(zhēng)搶的情況:多條線程進(jìn)入同步塊并爭(zhēng)用鎖 | 雖然很多線程,但是沒有沖突:多條線程進(jìn)入同步塊,但是線程進(jìn)入時(shí)間錯(cuò)開因而并未爭(zhēng)搶鎖 | 自始至終只有一個(gè)線程:只有一個(gè)線程進(jìn)入同步塊 |
| 本質(zhì) | 互斥同步 | CAS操作代替互斥同步 | 取消同步操作 |
| 優(yōu)點(diǎn) | 不會(huì)空耗CPU | 不會(huì)阻塞 | 不阻塞,執(zhí)行效率高(只有第一次獲取偏向鎖時(shí)需要CAS操作,后面只是比對(duì)ThreadId) |
| 缺點(diǎn) | 阻塞,上下文切換,重量級(jí)操作 | 長(zhǎng)時(shí)間獲取不到鎖空耗CPU | 適用場(chǎng)景太局限。若競(jìng)爭(zhēng)產(chǎn)生,會(huì)有額外的偏向鎖撤銷的消耗 |
不同的鎖有不同特點(diǎn),每種鎖只有在其特定的場(chǎng)景下,才會(huì)有出色的表現(xiàn),java中沒有哪種鎖能夠在所有情況下都能有出色的效率,引入這么多鎖的原因就是為了應(yīng)對(duì)不同的情況。
轉(zhuǎn)載于:https://my.oschina.net/u/3866531/blog/2050750
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【synchronized底层原理之4】锁的升级过程及比较的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【java】【mybatis】在使用my
- 下一篇: Redux专题:实用