日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程Monitor工作原理

發(fā)布時間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程Monitor工作原理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

🍎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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。