更新時(shí)間:2020-11-25 17:54:54 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽2193次
在java中,每個(gè)對(duì)象都有兩個(gè)池,鎖池和等待池。Java平臺(tái)中,因?yàn)橛袃?nèi)置鎖的機(jī)制,每個(gè)對(duì)象都可以承擔(dān)鎖的功能。Java虛擬機(jī)會(huì)為每個(gè)對(duì)象維護(hù)兩個(gè)“隊(duì)列”(姑且稱之為“隊(duì)列”,盡管它不一定符合數(shù)據(jù)結(jié)構(gòu)上隊(duì)列的“先進(jìn)先出”原則):一個(gè)叫Entry Set(入口集),另外一個(gè)叫Wait Set(等待集)。對(duì)于任意的對(duì)objectX,objectX的Entry Set用于存儲(chǔ)等待獲取objectX這個(gè)鎖的所有線程,也就是傳說(shuō)中的鎖池,objectX的Wait Set用于存儲(chǔ)執(zhí)行了objectX.wait()/wait(long)的線程,也就是等待池。
下面我們來(lái)看鎖池和等待池的具體介紹:
鎖池:假設(shè)線程A已經(jīng)擁有了某個(gè)對(duì)象(注意:不是類(lèi))的鎖,而其它的線程想要調(diào)用這個(gè)對(duì)象的某個(gè)synchronized方法(或者synchronized塊),由于這些線程在進(jìn)入對(duì)象的synchronized方法之前必須先獲得該對(duì)象的鎖的擁有權(quán),但是該對(duì)象的鎖目前正被線程A擁有,所以這些線程就進(jìn)入了該對(duì)象的鎖池中。
等待池:假設(shè)一個(gè)線程A調(diào)用了某個(gè)對(duì)象的wait()方法,線程A就會(huì)釋放該對(duì)象的鎖(因?yàn)閣ait()方法必須出現(xiàn)在synchronized中,這樣自然在執(zhí)行wait()方法之前線程A就已經(jīng)擁有了該對(duì)象的鎖),同時(shí)線程A就進(jìn)入到了該對(duì)象的等待池中。如果另外的一個(gè)線程調(diào)用了相同對(duì)象的notifyAll()方法,那么處于該對(duì)象的等待池中的線程就會(huì)全部進(jìn)入該對(duì)象的鎖池中,準(zhǔn)備爭(zhēng)奪鎖的擁有權(quán)。如果另外的一個(gè)線程調(diào)用了相同對(duì)象的notify()方法,那么僅僅有一個(gè)處于該對(duì)象的等待池中的線程(隨機(jī))會(huì)進(jìn)入該對(duì)象的鎖池。
設(shè)objectX是任意一個(gè)對(duì)象,假設(shè)有線程A、B、C同時(shí)申請(qǐng)objectX這個(gè)對(duì)象鎖,那么由于任意一個(gè)時(shí)刻只有一個(gè)線程能夠獲得(占用/持有)這個(gè)鎖,因此除了勝出(即獲得了鎖)的線程(這里假設(shè)是B)外,其他線程(這里就是A和C)都會(huì)被暫停(線程的生命周期狀態(tài)會(huì)被調(diào)整為BLOCKED)。這些因申請(qǐng)鎖而落選的線程就會(huì)被存入objectX對(duì)應(yīng)的鎖池之中。當(dāng)objectX被其持有線程(這里就是B)釋放時(shí),鎖池中的一個(gè)任意(注意是“任意”,而不一定是鎖池中等待時(shí)間最長(zhǎng)或者最短的)線程會(huì)被喚醒(即線程的生命周期狀態(tài)變更為RUNNABLE)。這個(gè)被喚醒的線程會(huì)與其他活躍線程(即不處于鎖池之中,且線程的生命周期狀態(tài)為RUNNABLE的線程)再次搶占o(jì)bjectX。這時(shí),被喚醒的線程如果成功申請(qǐng)到objectX,那么該線程就從鎖池中移除。否則,被喚醒的線程仍然會(huì)停留在鎖池中,并再次被暫停,以等待下次申請(qǐng)鎖的機(jī)會(huì)。
如果有個(gè)線程執(zhí)行了objectX.wait(),那么該線程就會(huì)被暫停(線程的生命周期狀態(tài)會(huì)被調(diào)整為Waiting),并且會(huì)釋放掉objectX鎖,然后被存入objectX的等待池之中。此時(shí),該線程就被稱為objectX的等待線程。當(dāng)其他線程執(zhí)行了objectX.notify()/notifyAll()時(shí),等待池中的一個(gè)(或者多個(gè),取決于被調(diào)用的是notify還是notifyAll方法)任意(注意是“任意”,而不一定是等待池中等待時(shí)間最長(zhǎng)或者最短的)等待線程會(huì)被喚醒,這些被喚醒的線程會(huì)被放到鎖池中,會(huì)與鎖池中已經(jīng)存在的線程以及其他(可能的)活躍線程共同參與搶奪objectX。至于代碼中到底是使用notify還是notifyAll方法,這個(gè)要根據(jù)實(shí)際情況來(lái)分析。
實(shí)際上Java鎖池和等待池的概念在Java中并不多見(jiàn),因此,Java鎖池和等待池的相關(guān)知識(shí)也容易被人忽視。不過(guò),慶幸的是,在本站的Java多線程教程中有詳細(xì)的講解,想要拓展知識(shí)的小伙伴趕緊抓住機(jī)會(huì)前去學(xué)習(xí)吧!
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)