synchronized背后的monitor鎖實(shí)現(xiàn)詳解_第1頁(yè)
synchronized背后的monitor鎖實(shí)現(xiàn)詳解_第2頁(yè)
synchronized背后的monitor鎖實(shí)現(xiàn)詳解_第3頁(yè)
synchronized背后的monitor鎖實(shí)現(xiàn)詳解_第4頁(yè)
synchronized背后的monitor鎖實(shí)現(xiàn)詳解_第5頁(yè)
已閱讀5頁(yè),還剩1頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第synchronized背后的monitor鎖實(shí)現(xiàn)詳解目錄獲取和釋放monitor鎖的時(shí)機(jī)用javap命令查看反匯編的結(jié)果同步代碼塊同步方法

獲取和釋放monitor鎖的時(shí)機(jī)

本文我們研究下synchronized背后的monitor鎖。

我們都知道,最簡(jiǎn)單的同步方式就是利用synchronized關(guān)鍵字來修飾代碼塊或者修飾一個(gè)方法,那么這部分被保護(hù)的代碼,在同一時(shí)刻就最多只有一個(gè)線程可以運(yùn)行,而synchronized的背后正是利用monitor鎖實(shí)現(xiàn)的。所以首先我們來看下獲取和釋放monitor鎖的時(shí)機(jī),每個(gè)Java對(duì)象都可以用作一個(gè)實(shí)現(xiàn)同步的鎖,這個(gè)鎖也被稱為內(nèi)置鎖或monitor鎖,獲得monitor鎖的唯一途徑就是進(jìn)入由這個(gè)鎖保護(hù)的同步代碼塊或同步方法,線程在進(jìn)入被synchronized保護(hù)的代碼塊之前,會(huì)自動(dòng)獲取鎖,并且無論是正常路徑退出,還是通過拋出異常退出,在退出的時(shí)候都會(huì)自動(dòng)釋放鎖。

我們首先來看一個(gè)synchronized修飾方法的代碼的例子:

publicsynchronizedvoidmethod(){

methodbody

我們看到method()方法是被synchronized修飾的,為了方便理解其背后的原理,我們把上面這段代碼改寫為下面這種等價(jià)形式的偽代碼。

publicvoidmethod(){

rinsicLock.lock();

try{

methodbody

finally{

rinsicLock.unlock();

在這種寫法中,進(jìn)入method方法后,立刻添加內(nèi)置鎖,并且用try代碼塊把方法保護(hù)起來,最后用finally釋放這把鎖,這里的intrinsicLock就是monitor鎖。經(jīng)過這樣的偽代碼展開之后,相信你對(duì)synchronized的理解就更加清晰了。

用javap命令查看反匯編的結(jié)果

JVM實(shí)現(xiàn)synchronized方法和synchronized代碼塊的細(xì)節(jié)是不一樣的,下面我們就分別來看一下兩者的實(shí)現(xiàn)。

同步代碼塊

首先我們來看下同步代碼塊的實(shí)現(xiàn),如代碼所示。

publicclassSynTest{

publicvoidsynBlock(){

synchronized(this){

System.out.println("lagou");

在SynTest類中的synBlock方法,包含一個(gè)同步代碼塊,synchronized代碼塊中有一行代碼打印了lagou字符串,下面我們來通過命令看下synchronized關(guān)鍵字到底做了什么事情:首先用cd命令切換到SynTest.java類所在的路徑,然后執(zhí)行javacSynTest.java,于是就會(huì)產(chǎn)生一個(gè)名為SynTest.class的字節(jié)碼文件,然后我們執(zhí)行javap-verboseSynTest.class,就可以看到對(duì)應(yīng)的反匯編內(nèi)容。

關(guān)鍵信息如下:

publicvoidsynBlock();

descriptor:()V

flags:ACC_PUBLIC

Code:

stack=2,locals=3,args_size=1

0:aload_0

1:dup

2:astore_1

3:monitorenter

4:getstatic#2//Fieldjava/lang/System.out:Ljava/io/PrintStream;

7:ldc#3//Stringlagou

9:invokevirtual#4//Methodjava/io/PrintStream.println:(Ljava/lang/String;)V

12:aload_1

13:monitorexit

14:goto22

17:astore_2

18:aload_1

19:monitorexit

20:aload_2

21:athrow

22:return

從里面可以看出,synchronized代碼塊實(shí)際上多了monitorenter和monitorexit指令,標(biāo)紅的第3、13、19行指令分別對(duì)應(yīng)的是monitorenter和monitorexit。這里有一個(gè)monitorenter,卻有兩個(gè)monitorexit指令的原因是,JVM要保證每個(gè)monitorenter必須有與之對(duì)應(yīng)的monitorexit,monitorenter指令被插入到同步代碼塊的開始位置,而monitorexit需要插入到方法正常結(jié)束處和異常處兩個(gè)地方,這樣就可以保證拋異常的情況下也能釋放鎖

可以把執(zhí)行monitorenter理解為加鎖,執(zhí)行monitorexit理解為釋放鎖,每個(gè)對(duì)象維護(hù)著一個(gè)記錄著被鎖次數(shù)的計(jì)數(shù)器。未被鎖定的對(duì)象的該計(jì)數(shù)器為0,我們來具體看一下monitorenter和monitorexit的含義:

monitorenter

執(zhí)行monitorenter的線程嘗試獲得monitor的所有權(quán),會(huì)發(fā)生以下這三種情況之一:

a.如果該monitor的計(jì)數(shù)為0,則線程獲得該monitor并將其計(jì)數(shù)設(shè)置為1。然后,該線程就是這個(gè)monitor的所有者。

b.如果線程已經(jīng)擁有了這個(gè)monitor,則它將重新進(jìn)入,并且累加計(jì)數(shù)。

c.如果其他線程已經(jīng)擁有了這個(gè)monitor,那個(gè)這個(gè)線程就會(huì)被阻塞,直到這個(gè)monitor的計(jì)數(shù)變成為0,代表這個(gè)monitor已經(jīng)被釋放了,于是當(dāng)前這個(gè)線程就會(huì)再次嘗試獲取這個(gè)monitor。

monitorexitmonitorexit的作用是將monitor的計(jì)數(shù)器減1,直到減為0為止。代表這個(gè)monitor已經(jīng)被釋放了,已經(jīng)沒有任何線程擁有它了,也就代表著解鎖,所以,其他正在等待這個(gè)monitor的線程,此時(shí)便可以再次嘗試獲取這個(gè)monitor的所有權(quán)。

同步方法

從上面可以看出,同步代碼塊是使用monitorenter和monitorexit指令實(shí)現(xiàn)的。而對(duì)于synchronized方法,并不是依靠monitorenter和monitorexit指令實(shí)現(xiàn)的,被javap反匯編后可以看到,synchronized方法和普通方法大部分是一樣的,不同在于,這個(gè)方法會(huì)有一個(gè)叫作ACC_SYNCHRONIZED的flag修飾符,來表明它是同步方法。

同步方法的代碼如下所示。

publicsynchronizedvoidsynMethod(){

對(duì)應(yīng)的反匯編指令如下所示。

publicsynchronizedvoidsynMethod();

descriptor:()V

flags:ACC_PUBLIC,ACC_SYNCHRONIZED

Code:

stack=0,locals=1,args_size=1

0:return

LineNumberTable:

line16:0

可以看出,被synchronized修飾的方法會(huì)有一個(gè)ACC_SYNCHRONIZED標(biāo)志。當(dāng)某個(gè)線程要訪問某個(gè)方法的時(shí)候,會(huì)首先檢查方法是否有ACC_SYNCHRONIZED標(biāo)志,如果有則需要先獲得monitor鎖,然后才能開始執(zhí)行方法,方法執(zhí)行之后再釋放monitor鎖。其他方面,synchronized方法和剛才的synchronized代碼塊是很類似的,例如這時(shí)如果其他線程來請(qǐng)求執(zhí)行方法,也會(huì)因?yàn)闊o法獲得monitor鎖而被阻塞。

好了,本文的內(nèi)容就全部講完了,我們講解了獲取和釋放monitor的時(shí)機(jī),以及被synchronized修飾的等

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論