synchronized (this)原理
涉及兩條指令:(1)monitorenter
每個(gè)對(duì)象有一個(gè)監(jiān)視器鎖(monitor)。當(dāng)monitor被占用時(shí)就會(huì)處于鎖定狀態(tài),線程執(zhí)行monitorenter指令時(shí)嘗試獲取monitor的所有權(quán)啥供,過(guò)程如下:
1纱新、如果monitor的進(jìn)入數(shù)為0,則該線程進(jìn)入monitor申钩,然后將進(jìn)入數(shù)設(shè)置為1叉袍,該線程即為monitor的所有者始锚。
2、如果線程已經(jīng)占有該monitor喳逛,只是重新進(jìn)入瞧捌,則進(jìn)入monitor的進(jìn)入數(shù)加1。
3艺配、如果其他線程已經(jīng)占用了monitor察郁,則該線程進(jìn)入阻塞狀態(tài),直到monitor的進(jìn)入數(shù)為0转唉,再重新嘗試獲取monitor的所有權(quán)皮钠。
(2)monitorexit
執(zhí)行monitorexit的線程必須是objectref所對(duì)應(yīng)的monitor的所有者。
指令執(zhí)行時(shí)赠法,monitor的進(jìn)入數(shù)減1麦轰,如果減1后進(jìn)入數(shù)為0,那線程退出monitor砖织,不再是這個(gè)monitor的所有者款侵。其他被這個(gè)monitor阻塞的線程可以嘗試去獲取這個(gè)
monitor 的所有權(quán)。
通過(guò)這兩段描述侧纯,我們應(yīng)該能很清楚的看出synchronized的實(shí)現(xiàn)原理新锈,synchronized的語(yǔ)義底層是通過(guò)一個(gè)monitor的對(duì)象來(lái)完成。
其實(shí)wait/notify等方法也依賴于monitor對(duì)象眶熬,這就是為什么只有在同步的塊或者方法中才能調(diào)用wait/notify等方法妹笆,否則會(huì)拋出java.lang.IllegalMonitorStateException的異常的原因。
同步方法
public synchronized void method() {
System.out.println("Hello World!");
}
從反編譯的結(jié)果來(lái)看娜氏,方法的同步并沒(méi)有通過(guò)指令monitorenter和monitorexit來(lái)完成(理論上其實(shí)也可以通過(guò)這兩條指令來(lái)實(shí)現(xiàn))拳缠。
相對(duì)于普通方法,其常量池中多了ACC_SYNCHRONIZED標(biāo)示符贸弥。
JVM就是根據(jù)該標(biāo)示符來(lái)實(shí)現(xiàn)方法的同步的:當(dāng)方法被調(diào)用時(shí)窟坐,調(diào)用指令將會(huì)檢查方法的 ACC_SYNCHRONIZED 訪問(wèn)標(biāo)志是否被設(shè)置,如果設(shè)置了绵疲,執(zhí)行線程將先獲取monitor哲鸳,獲取成功之后才能執(zhí)行方法體,方法執(zhí)行完后再釋放monitor最岗。在方法執(zhí)行期間帕胆,其他任何線程都無(wú)法再獲得同一個(gè)monitor對(duì)象。 其實(shí)本質(zhì)上沒(méi)有區(qū)別般渡,只是方法的同步是一種隱式的方式來(lái)實(shí)現(xiàn)懒豹,無(wú)需通過(guò)字節(jié)碼來(lái)完成。