多线程Monitor工作原理
🍎1. 什么是Monitor?
我們都知道synchronized的作用是用來保證修飾的代碼或者方法執(zhí)行有且只有一個線程執(zhí)行,也就是鎖。那么在執(zhí)行被鎖住的方式時,synchronized就需要通過monitor來記錄和保證鎖的狀態(tài)。所以monitor這里的作用其實就是起到了控制synchronized什么時候獲取鎖,什么時候釋放鎖,以及記錄了鎖被重用的次數(shù)。🍎2. 當多線程時Monitor如何執(zhí)行
前置知識了解
owner : 指向的是當前獲得線程的地址,用來判斷當前鎖是被哪個線程持有。
waitSet : 是指已經(jīng)獲取得一次鎖了,對象調(diào)用了wait方法,講當前線程掛起了就進入了等待隊列。等待時間到期的時候喚醒,或者其他線程喚醒。
entryList : 是隊列用來獲取鎖的緩沖區(qū),用來將cxq和waitSet中的數(shù)據(jù) 移動到entryList進行排隊。這個統(tǒng)一獲取鎖的入口。一般是cxq 或者waitSet數(shù)據(jù)復制過來進行統(tǒng)一排隊。
執(zhí)行流程
剛開始Monitor中Owner為null當Thread-2執(zhí)行synchronized(obj)就會將Monitor的所有者Owner置為Thread-2,Monitor中只能有一個Owner
在Thread-2上鎖的過程中,如果Thread-3,Thread-.4,Thread-5也來執(zhí)行synchronized(obj),就會進入EntryList BLOCKED(阻塞)
Thread-2執(zhí)行完同步代碼塊的內(nèi)容,然后喚醒EntryList中等待的線程來競爭鎖,競爭的時是非公平的圖中WaitSet中的Thread-0,Thread-1是之前獲得過鎖,但條件不滿足進入WAITING狀態(tài)的線程,
🍎3. 以為字節(jié)碼舉例
對于被synchronized修飾的代碼塊,在生成class字節(jié)碼文件中會出現(xiàn)monitorenter、monitorexit。如下面例子所示:
public void synBlock();descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=3, args_size=10: aload_01: dup2: astore_13: monitorenter #14: getstatic 7: ldc 9: invokevirtual 12: aload_113: monitorexit #214: goto 17: astore_218: aload_119: monitorexit #320: aload_221: athrow22: return執(zhí)行monitorenter的線程會嘗試獲取monitor的所有權(quán),會發(fā)生以下三種情況之一:
如果該monitor的計數(shù)為0,這線程獲得該monitor鎖并設置為1如果當前線程有了這個monitor鎖,則該線程的monitor的計數(shù)累加1
如果其他線程嘗試獲取monitor鎖,發(fā)現(xiàn)monitor的計數(shù)不為0,這表示當前線程被其他線程占用,則阻塞,直到這個monitor鎖的計數(shù)變?yōu)?,然后再重新嘗試獲取。
執(zhí)行monitorexit的線程就會將montior的計數(shù)減1,直到減到0為止,這時候就表示可以釋放當前montior的鎖了,其他的線程就可以嘗試來獲取當前代碼的鎖了。
看到這里,可能會有疑問,為什么生成的字節(jié)碼文件中,一個monitorenter為什么對存在兩個monitorexit,這里其實是考慮到代碼發(fā)生了異常的情況,當我們在正常執(zhí)行完任務之后,會執(zhí)行#2的monitorexit去釋放鎖,但是出現(xiàn)異常了就會去執(zhí)行#3的monitorexit的鎖。這樣就避免了死鎖的發(fā)生,保證在任何情況下都能正常釋放鎖。
被修飾的同步方法
同步代碼塊是使用monitorenter和monitorexit來實現(xiàn)的,對于方法則不是依靠它兩來實現(xiàn)的而是通過一個ACC_SYNCHRONIZED的flag修飾符,源代碼如下:
public synchronized void synMethod();descriptor: ()Vflags: ACC_PUBLIC, ACC_SYNCHRONIZEDCode:stack=0, locals=1, args_size=10: returnLineNumberTable:line 16: 0當某個線程需要訪問這個方法的時候,會先檢查這個方法是否有ACC_SYNCHRONIZED這個標簽,如果有就需要先獲取monitor鎖,其他的方面和同步代碼塊的邏輯是一樣的。
總結(jié)
以上是生活随笔為你收集整理的多线程Monitor工作原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux more 下一页_Linux
- 下一篇: 服务器CPU和普通CPU有什么区别?常用