溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java中synchronized的作用及用法

發(fā)布時(shí)間:2021-06-18 16:04:38 來(lái)源:億速云 閱讀:263 作者:chen 欄目:編程語(yǔ)言

這篇文章主要講解了“Java中synchronized的作用及用法”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java中synchronized的作用及用法”吧!

synchronized同步關(guān)鍵字簡(jiǎn)介

synchronized是屬于JVM層面的一個(gè)關(guān)鍵字,底層是通過(guò)一個(gè)monitor對(duì)象(管程對(duì)象)來(lái)完成,由于wait()/notify()等方法也依賴于monitor對(duì)象,所以只有在同步的塊或者方法中才能調(diào)用wait/notify等方法

Java中synchronized的作用及用法

Java中synchronized的作用及用法

synchronized同步代碼塊底層實(shí)現(xiàn)

  • synchronized同步語(yǔ)句塊的實(shí)現(xiàn)使用monitorentermonitorexit 指令。

    • monitorenter:指令指向同步代碼塊的開(kāi)始位置

    • monitorexit:指令則指明同步代碼塊的結(jié)束位置

synchronized獲取鎖

  • 當(dāng)執(zhí)行monitorenter指令時(shí),當(dāng)前線程將試圖獲取 objectref(即對(duì)象鎖) 所對(duì)應(yīng)的 monitor的持有權(quán),當(dāng) objectref的monitor 的進(jìn)入計(jì)數(shù)器**為0,那線程可以成功取得 monitor,并將計(jì)數(shù)器值設(shè)置為 1,取鎖成功。

  • 如果當(dāng)前線程已經(jīng)擁有 objectref 的 monitor 的持有權(quán),那它可以重入這個(gè) monitor (關(guān)于重入性稍后會(huì)分析),重入時(shí)計(jì)數(shù)器的值也會(huì)加 1。

  • 倘若其他線程已經(jīng)擁有objectref 的 monitor 的所有權(quán),那當(dāng)前線程將被阻塞,直到正在執(zhí)行線程執(zhí)行完畢,即monitorexit指令被執(zhí)行,執(zhí)行線程將釋放monitor(鎖)并設(shè)置計(jì)數(shù)器值為0,其他線程將有機(jī)會(huì)持有 monitor ;**

為了保證在方法異常完成時(shí) monitorenter 和 monitorexit 指令依然可以正確配對(duì)執(zhí)行,編譯器會(huì)自動(dòng)產(chǎn)生一個(gè)異常處理器,這個(gè)異常處理器聲明可處理所有的異常,它的目的就是用來(lái)執(zhí)行 monitorexit 指令。

從字節(jié)碼中也可以看出多了一個(gè)monitorexit指令,它就是異常結(jié)束時(shí)被執(zhí)行的釋放monitor的指令;

monitorenter(進(jìn)入管程對(duì)象)

每個(gè)對(duì)象有一個(gè)管程對(duì)象(monitor),當(dāng)monitor被占用時(shí)就會(huì)處于鎖定狀態(tài);線程執(zhí)行monitorenter指令時(shí)嘗試獲取monitor的所有權(quán),過(guò)程如下:

  1. 如果monitor的進(jìn)入計(jì)數(shù)器為0,則該線程進(jìn)入monitor,然后將進(jìn)入計(jì)數(shù)器設(shè)置為1,該線程即為monitor的所有者;

  2. 如果線程已經(jīng)之前占用了該monitor,本次只是重新進(jìn)入,則將monitor的進(jìn)入計(jì)數(shù)器加1;

  3. 如果其他線程已經(jīng)占用了monitor,則該線程進(jìn)入阻塞狀態(tài),直到monitor的進(jìn)入計(jì)數(shù)器為0,再重新嘗試獲取monitor的所有權(quán);

monitorexit(退出管程對(duì)象)
  • 執(zhí)行monitorexit的線程必須是objectref(即對(duì)象鎖)所對(duì)應(yīng)的monitor的所有者;

  • 指令執(zhí)行時(shí),monitor的進(jìn)入計(jì)數(shù)器減1,如果減1后進(jìn)入計(jì)數(shù)器為0,那線程退出monitor,不再是這個(gè)monitor的所有者。其他被這個(gè)monitor阻塞的線程可以嘗試去獲取這個(gè) monitor 的所有權(quán).

同步方法中synchronized底層實(shí)現(xiàn)

方法級(jí)的同步是隱式,即無(wú)需通過(guò)字節(jié)碼指令(monitorenter和monitorexit)來(lái)控制的。 Java中synchronized的作用及用法 Java中synchronized的作用及用法 它實(shí)現(xiàn)在方法調(diào)用和返回操作之中。

  • JVM可以從方法常量池中的方法表結(jié)構(gòu)(method_info Structure) 中的ACC_SYNCHRONIZED訪問(wèn)標(biāo)志區(qū)分一個(gè)方法是否同步方法。

  • 當(dāng)方法調(diào)用時(shí),調(diào)用指令將會(huì)檢查方法的 ACC_SYNCHRONIZED 訪問(wèn)標(biāo)志是否被設(shè)置,如果設(shè)置了,執(zhí)行線程將先持有monitor(虛擬機(jī)規(guī)范中用的是管程一詞)。

  • 然后再執(zhí)行方法,最后在方法完成(無(wú)論是正常完成還是非正常完成)時(shí)釋放monitor。

在方法執(zhí)行期間,執(zhí)行線程持有了monitor,其他任何線程都無(wú)法再獲得同一個(gè)monitor。如果一個(gè)同步方法執(zhí)行期間拋出了異常,并且在方法內(nèi)部無(wú)法處理此異常,那這個(gè)同步方法所持有的monitor將在異常拋到同步方法之外時(shí)自動(dòng)釋放。


感謝各位的閱讀,以上就是“Java中synchronized的作用及用法”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java中synchronized的作用及用法這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI