synchronized底層原理
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
作者 | zwy2021
來源 | urlify.cn/UZFj6b
76套java從入門到精通實(shí)戰(zhàn)課程分享
通過反編譯class文件,可以看到synchronized最關(guān)鍵的部分是monitor對(duì)象。
又因?yàn)閟ynchronized關(guān)鍵字使用的方法不同,可以將monitor對(duì)象使用分為以下兩種情況。
synchronized放在方法簽名上
public synchronized void method(){
}
這時(shí)候在反編譯文件里,該方法的ACC_SYNCHRONIZED訪問標(biāo)志位會(huì)被標(biāo)記

synchronized作為對(duì)象鎖
public void method(){
synchronized(new Object()){
}
}
這時(shí)候ACC_SYNCHRONIZED并不會(huì)被標(biāo)記,但是會(huì)執(zhí)行monitorenter和monitorexit命令,從而實(shí)現(xiàn)同步。
可以看到雖然只有一個(gè)monitorenter但是有兩個(gè)monitorexit,這是因?yàn)橛袃煞N情況可以讓當(dāng)前線程放棄鎖,即
當(dāng)前synchronized代碼塊運(yùn)行完
發(fā)生中斷

monitor對(duì)象
其實(shí)以上兩種方法都是相同的,ACC_SYNCHRONIZED標(biāo)志位是隱式調(diào)用了monitor對(duì)象而已。下面來說一下monitor對(duì)象以及它是如何實(shí)現(xiàn)運(yùn)作的。
monitor的數(shù)據(jù)結(jié)構(gòu)

關(guān)于存儲(chǔ)的monitor對(duì)象有以下三種可能,對(duì)應(yīng)不同的synchronzied使用方式,
synchronzied修飾普通方法——>鎖的是this,也就是調(diào)用當(dāng)前方法的實(shí)例對(duì)象
synchronized修飾代碼塊——>鎖的是synchronized后面括號(hào)里的方法
synchronized修飾static方法——>鎖的是類的.class對(duì)象
關(guān)于面試的時(shí)候會(huì)問的各種情況下會(huì)不會(huì)同步執(zhí)行,牢記一點(diǎn)
鎖的對(duì)象相同才會(huì)同步執(zhí)行
鎖的對(duì)象相同才會(huì)同步執(zhí)行
鎖的對(duì)象相同才會(huì)同步執(zhí)行
也就是說,類鎖對(duì)普通方法鎖是不存在覆蓋的,下面兩個(gè)方法不會(huì)同步執(zhí)行
public synchronized void method1(){
}
public static synchronized void method2(){
}
monitor運(yùn)行機(jī)制
如果一個(gè)線程運(yùn)行到一個(gè)同步代碼塊,如果線程進(jìn)入數(shù)為0,則該線程可擁有此monitor對(duì)象的鎖,遇到monitorenter,進(jìn)入數(shù)+1,遇到monitorexit,進(jìn)入數(shù)-1。
如果目前線程進(jìn)入數(shù)不為0,則當(dāng)前線程不能獲得此monitor對(duì)象的鎖,需要等待。
synchronized的可重入性,不可中斷性是如何保障的呢?
monitor對(duì)象的線程進(jìn)入數(shù)不是0和1,如果發(fā)生重入,進(jìn)入數(shù)+1即可。
不可中斷性:一個(gè)線程獲取鎖后,其他線程必須阻塞或等待,不能搶占,按照上面的運(yùn)行機(jī)制,必須線程進(jìn)入數(shù)=0其他線程才能獲得鎖,因而,不可中斷性實(shí)現(xiàn)。
另外,有的面試題會(huì)問非同步方法和同步方法同時(shí)調(diào)用會(huì)不會(huì)同步執(zhí)行,答案是不會(huì)。
因?yàn)椋峭椒椒▓?zhí)行時(shí)不會(huì)去考慮線程進(jìn)入數(shù)以及獲得鎖一系列流程,直接開始執(zhí)行,怎么可能同步執(zhí)行呢


