synchronize原理
?
synchronized的三種應(yīng)用方式
一. 修飾實(shí)例方法,作用于當(dāng)前實(shí)例加鎖,進(jìn)入同步代碼前要獲得當(dāng)前實(shí)例的鎖。
二. 修飾靜態(tài)方法,作用于當(dāng)前類對(duì)象加鎖,進(jìn)入同步代碼前要獲得當(dāng)前類對(duì)象的鎖。
三. 修飾代碼塊,指定加鎖對(duì)象,對(duì)給定對(duì)象加鎖,進(jìn)入同步代碼庫(kù)前要獲得給定對(duì)象。
synchronized的字節(jié)碼指令
synchronized同步塊使用了monitorenter和monitorexit指令實(shí)現(xiàn)同步,這兩個(gè)指令,本質(zhì)上都是對(duì)一個(gè)對(duì)象的監(jiān)視器(monitor)進(jìn)行獲取,這個(gè)過(guò)程是排他的,也就是說(shuō)同一時(shí)刻只能有一個(gè)線程獲取到由synchronized所保護(hù)對(duì)象的監(jiān)視器。
線程執(zhí)行到monitorenter指令時(shí),會(huì)嘗試獲取對(duì)象所對(duì)應(yīng)的monitor所有權(quán),也就是嘗試獲取對(duì)象的鎖,而執(zhí)行monitorexit,就是釋放monitor的所有權(quán)。
synchronized的鎖的原理
兩個(gè)重要的概念:一個(gè)是對(duì)象頭,另一個(gè)是monitor。
Java對(duì)象頭
在Hotspot虛擬機(jī)中,對(duì)象在內(nèi)存中的布局分為三塊區(qū)域:對(duì)象頭(Mark Word、Class Metadata Address)、實(shí)例數(shù)據(jù)和對(duì)齊填充;Java對(duì)象頭是實(shí)現(xiàn)synchronized的鎖對(duì)象的基礎(chǔ)。一般而言,synchronized使用的鎖對(duì)象是存儲(chǔ)在Java對(duì)象頭里。它是輕量級(jí)鎖和偏向鎖的關(guān)鍵。
Mark Word
Mark Word用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的
鎖、偏向線程 ID、偏向時(shí)間戳等等。Java對(duì)象頭一般占有兩個(gè)機(jī)器碼(在32位虛擬機(jī)中,1個(gè)機(jī)器碼等于4字節(jié),
也就是32bit)。
?
?
Class Metadata Address
類型指針,即是對(duì)象指向它的類的元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類的實(shí)例。
Array length
如果對(duì)象是一個(gè)Java數(shù)組,那在對(duì)象頭中還必須有一塊用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù)。
Monitor
Monitor是一個(gè)同步工具,它內(nèi)置于每一個(gè)Object對(duì)象中,相當(dāng)于一個(gè)許可證。拿到許可證即可以進(jìn)行操作,沒(méi)有拿到則需要阻塞等待。
在hotspot虛擬機(jī)中,通過(guò)ObjectMonitor類來(lái)實(shí)現(xiàn)monitor。
?
?
synchronized鎖的優(yōu)化
jdk1.6以后對(duì)synchronized的鎖進(jìn)行了優(yōu)化,引入了偏向鎖、輕量級(jí)鎖,鎖的級(jí)別從低到高逐步升級(jí):?
無(wú)鎖->偏向鎖->輕量級(jí)鎖->重量級(jí)鎖
自旋鎖與自適應(yīng)自旋
線程的掛起和恢復(fù)會(huì)極大的影響開(kāi)銷。并且jdk官方人員發(fā)現(xiàn),很多線程在等待鎖的時(shí)候,在很短的一段時(shí)間就獲得了鎖,所以它們?cè)诰€程等待的時(shí)候,并不需要把線程掛起,而是讓他無(wú)目的的循環(huán),一般設(shè)置10次。這樣就避免了線程切換的開(kāi)銷,極大的提升了性能。
而適應(yīng)性自旋,是賦予了自旋一種學(xué)習(xí)能力,它并不固定自旋10次一下。他可以根據(jù)它前面線程的自旋情況,從而調(diào)整它的自旋,甚至是不經(jīng)過(guò)自旋而直接掛起。
鎖消除
對(duì)不會(huì)存在線程安全的鎖進(jìn)行消除。
鎖粗化
如果jvm檢測(cè)到有一串零碎的操作都對(duì)同一個(gè)對(duì)象加鎖,將會(huì)把鎖粗化到整個(gè)操作外部,如循環(huán)體。
偏向鎖
多數(shù)情況下,鎖不僅不存在多線程競(jìng)爭(zhēng),而且總是由同一線程多次獲得,為了讓其獲得鎖的代價(jià)更低而引入了偏向鎖。
當(dāng)一個(gè)線程訪問(wèn)同步塊并獲取鎖時(shí),會(huì)在對(duì)象頭和棧幀中的鎖記錄里存儲(chǔ)鎖偏向的線程ID,以后該線程在進(jìn)入和退出同步塊時(shí)不需要進(jìn)行CAS操作來(lái)加鎖和解鎖,只需簡(jiǎn)單地測(cè)試一下對(duì)象頭的Mark Word里是否存儲(chǔ)著指向當(dāng)前線程的偏向鎖。
如果測(cè)試成功,表示線程已經(jīng)獲得了鎖。
如果測(cè)試失敗,則需要再測(cè)試一下Mark Word中偏向鎖的標(biāo)識(shí)是否設(shè)置成01(表示當(dāng)前是偏向鎖)。
如果沒(méi)有設(shè)置,則使用CAS競(jìng)爭(zhēng)鎖。
如果設(shè)置了,則嘗試使用CAS將對(duì)象頭的偏向鎖指向當(dāng)前線程。
輕量級(jí)鎖
引入輕量級(jí)鎖的主要目的是在多線程競(jìng)爭(zhēng)不激烈的情況下,通過(guò)CAS競(jìng)爭(zhēng)鎖,減少傳統(tǒng)的重量級(jí)鎖使用操作系統(tǒng)互斥量產(chǎn)生的性能消耗。
重量級(jí)鎖
重量級(jí)鎖通過(guò)對(duì)象內(nèi)部的監(jiān)視器(monitor)實(shí)現(xiàn),其中monitor的本質(zhì)是依賴于底層操作系統(tǒng)的Mutex Lock實(shí)現(xiàn),操作系統(tǒng)實(shí)現(xiàn)線程之間的切換需要從用戶態(tài)到內(nèi)核態(tài)的切換,切換成本非常高。
鎖升級(jí)
偏向鎖升級(jí)輕量級(jí)鎖:當(dāng)一個(gè)對(duì)象持有偏向鎖,一旦第二個(gè)線程訪問(wèn)這個(gè)對(duì)象,如果產(chǎn)生競(jìng)爭(zhēng),偏向鎖升級(jí)為輕量級(jí)鎖。
輕量級(jí)鎖升級(jí)重量級(jí)鎖:一般兩個(gè)線程對(duì)于同一個(gè)鎖的操作都會(huì)錯(cuò)開(kāi),或者說(shuō)稍微等待一下(自旋),另一個(gè)線程就會(huì)釋放鎖。但是當(dāng)自旋超過(guò)一定的次數(shù),或者一個(gè)線程在持有鎖,一個(gè)在自旋,又有第三個(gè)來(lái)訪時(shí),輕量級(jí)鎖膨脹為重量級(jí)鎖,重量級(jí)鎖使除了擁有鎖的線程以外的線程都阻塞,防止CPU空轉(zhuǎn)。
wait和notify的原理
調(diào)用wait方法,首先會(huì)獲取監(jiān)視器鎖,獲得成功以后,會(huì)讓當(dāng)前線程進(jìn)入等待狀態(tài)進(jìn)入等待隊(duì)列并且釋放鎖。
當(dāng)其他線程調(diào)用notify后,會(huì)選擇從等待隊(duì)列中喚醒任意一個(gè)線程,而執(zhí)行完notify方法以后,并不會(huì)立馬喚醒線程,原因是當(dāng)前的線程仍然持有這把鎖,處于等待狀態(tài)的線程無(wú)法獲得鎖。必須要等到當(dāng)前的線程執(zhí)行完按monitorexit指令以后,也就是鎖被釋放以后,處于等待隊(duì)列中的線程就可以開(kāi)始競(jìng)爭(zhēng)鎖了。
wait和notify為什么需要在synchronized里面?
wait方法的語(yǔ)義有兩個(gè),一個(gè)是釋放當(dāng)前的對(duì)象鎖、另一個(gè)是使得當(dāng)前線程進(jìn)入阻塞隊(duì)列,而這些操作都和監(jiān)視器是相關(guān)的,所以wait必須要獲得一個(gè)監(jiān)視器鎖。
而對(duì)于notify來(lái)說(shuō)也是一樣,它是喚醒一個(gè)線程,既然要去喚醒,首先得知道它在哪里,所以就必須要找到這個(gè)對(duì)象獲取到這個(gè)對(duì)象的鎖,然后到這個(gè)對(duì)象的等待隊(duì)列中去喚醒一個(gè)線程。
轉(zhuǎn)載于:https://www.cnblogs.com/heqiyoujing/p/11144649.html
總結(jié)
以上是生活随笔為你收集整理的synchronize原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 有没有朋友可以帮我解释一下贴水是什么意思
- 下一篇: 未来产品的设计