synchronized是java提供的原?性內(nèi)置鎖拇涤,這種內(nèi)置的并且使?者看不到的鎖也被稱為監(jiān)視器鎖娘荡,使?synchronized之后灭翔,會在編譯之后在同步的代碼塊前后加上monitorenter和monitorexit字節(jié)碼指令隙咸,它依賴操作系統(tǒng)底層互斥鎖實(shí)現(xiàn)账千。它的作?主要就是實(shí)現(xiàn)原?性操作和解決共享變量的內(nèi)存可?性問題汞贸。
執(zhí)?monitorenter指令時會嘗試獲取對象鎖绳军,如果對象沒有被鎖定或者已經(jīng)獲得了鎖印机,鎖的計(jì)數(shù)器+1。此時其他競爭鎖的線程則會進(jìn)?等待隊(duì)列中门驾。執(zhí)?monitorexit指令時則會把計(jì)數(shù)器-1射赛,當(dāng)計(jì)數(shù)器值為0時,則鎖釋放奶是,處于等待隊(duì)列中的線程再繼續(xù)競爭鎖楣责。
synchronized是排它鎖,當(dāng)?個線程獲得鎖之后聂沙,其他線程必須等待該線程釋放鎖后才能獲得鎖秆麸,?且由于Java中的線程和操作系統(tǒng)原?線程是??對應(yīng)的,線程被阻塞或者喚醒時時會從?戶態(tài)切換到內(nèi)核態(tài)及汉,這種轉(zhuǎn)換?常消耗性能沮趣。
從內(nèi)存語義來說,加鎖的過程會清除?作內(nèi)存中的共享變量坷随,再從主內(nèi)存讀取房铭,?釋放鎖的過程則是將?作內(nèi)存中的共享變量寫回主內(nèi)存。實(shí)際上?部分時候我認(rèn)為說到monitorenter就?了温眉,但是為了更清楚的描述缸匪,還是再具體?點(diǎn)。
如果再深?到源碼來說类溢,synchronized實(shí)際上有兩個隊(duì)列waitSet和entryList豪嗽。
1. 當(dāng)多個線程進(jìn)?同步代碼塊時,?先進(jìn)?entryList
2. 有?個線程獲取到monitor鎖后豌骏,就賦值給當(dāng)前線程龟梦,并且計(jì)數(shù)器+1
3. 如果線程調(diào)?wait?法,將釋放鎖窃躲,當(dāng)前線程置為null计贰,計(jì)數(shù)器-1,同時進(jìn)?waitSet等待被喚醒蒂窒,調(diào)?notify或者notifyAll之后?會進(jìn)?entryList競爭鎖
4. 如果線程執(zhí)?完畢躁倒,同樣釋放鎖,計(jì)數(shù)器-1洒琢,當(dāng)前線程置為null