溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

LockSupport.park()是否會釋放鎖資源嗎

發(fā)布時間:2021-12-21 09:17:49 來源:億速云 閱讀:224 作者:柒染 欄目:大數(shù)據(jù)

LockSupport.park()是否會釋放鎖資源嗎,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。


引子

大家知道,我最近在招人,今天遇到個同學(xué),他的源碼看過一些,然后我就開始了AQS連環(huán)問。

我:說說AQS的大致流程?

他:AQS包含一個狀態(tài)變量,一個同步隊列……balabala……互斥鎖balabala,共享鎖balabala……

我:AQS中除了同步隊列,還有什么隊列?

他:還有個Condition,Condition中有個條件隊列……

我:條件隊列和同步隊列有什么區(qū)別?

他:條件隊列balabala,然后調(diào)用LockSupport.park()進(jìn)入休眠,等待被喚醒,……,balabala

咦,這時我靈感突發(fā):LockSupport.park()和Thread.sleep()有什么區(qū)別?

他:Thread.sleep()不會釋放鎖資源,……,balabala

我:LockSupport.park()會釋放鎖資源嗎?

他:會吧。(估計和Object.wait()搞混淆了)

我:會嗎?會嗎?會嗎?

他(羞澀地低下了頭):彤哥,不知道,你的文章里沒寫。(這段我瞎寫的哈^^)

OK,今天我們就來看看LockSupport.park()到底會不會釋放鎖資源。

Thread.sleep()和Object.wait()的區(qū)別

首先,我們先來看看Thread.sleep()和Object.wait()的區(qū)別,這是一個爛大街的題目了,大家應(yīng)該都能說上來兩點(diǎn)。

(1)Thread.sleep()不會釋放占有的鎖,Object.wait()會釋放占有的鎖;

(2)Thread.sleep()必須傳入時間,Object.wait()可傳可不傳,不傳表示一直阻塞下去;

(3)Thread.sleep()到時間了會自動喚醒,然后繼續(xù)執(zhí)行;

(4)Object.wait()不帶時間的,需要另一個線程使用Object.notify()喚醒;

(5)Object.wait()帶時間的,假如沒有被notify,到時間了會自動喚醒,這時又分好兩種情況,一是立即獲取到了鎖,線程自然會繼續(xù)執(zhí)行;二是沒有立即獲取鎖,線程進(jìn)入同步隊列等待獲取鎖;

其實(shí),他們倆最大的區(qū)別就是Thread.sleep()不會釋放鎖資源,Object.wait()會釋放鎖資源。

Thread.sleep()和Condition.await()的區(qū)別

我們再來看看Thread.sleep()和Condition.await()的區(qū)別。

其實(shí),這個題目和上面的題目比較類似,因為本來Object.wait()和Condition.await()的原理就比較類似,可以參考之前彤哥寫的《死磕 java線程系列之線程的生命周期》之篇文章。

這個題目的回答思路跟Object.wait()是基本一致的,不同的是Condition.await()底層是調(diào)用LockSupport.park()來實(shí)現(xiàn)阻塞當(dāng)前線程的。

實(shí)際上,它在阻塞當(dāng)前線程之前還干了兩件事,一是把當(dāng)前線程添加到條件隊列中,二是“完全”釋放鎖,也就是讓state狀態(tài)變量變?yōu)?,然后才是調(diào)用LockSupport.park()阻塞當(dāng)前線程,可以參考之前彤哥寫的《死磕 java同步系列之ReentrantLock源碼解析(二)——條件鎖》這篇文章。

看到這里,今天開篇提的那個問題是不是就有答案了呢【本文由公從號“彤哥讀源碼”原創(chuàng)】?

Thread.sleep()和LockSupport.park()的區(qū)別

LockSupport.park()還有幾個兄弟方法——parkNanos()、parkUtil()等,我們這里說的park()方法統(tǒng)稱這一類方法。

(1)從功能上來說,Thread.sleep()和LockSupport.park()方法類似,都是阻塞當(dāng)前線程的執(zhí)行,且都不會釋放當(dāng)前線程占有的鎖資源

(2)Thread.sleep()沒法從外部喚醒,只能自己醒過來;

(3)LockSupport.park()方法可以被另一個線程調(diào)用LockSupport.unpark()方法喚醒;

(4)Thread.sleep()方法聲明上拋出了InterruptedException中斷異常,所以調(diào)用者需要捕獲這個異?;蛘咴賿伋?;

(5)LockSupport.park()方法不需要捕獲中斷異常;

(6)Thread.sleep()本身就是一個native方法;

(7)LockSupport.park()底層是調(diào)用的Unsafe的native方法;

Object.wait()和LockSupport.park()的區(qū)別

二者都會阻塞當(dāng)前線程的運(yùn)行,他們有什么區(qū)別呢?經(jīng)過上面的分析相信你一定很清楚了,真的嗎?往下看!

(1)Object.wait()方法需要在synchronized塊中執(zhí)行;

(2)LockSupport.park()可以在任意地方執(zhí)行;

(3)Object.wait()方法聲明拋出了中斷異常,調(diào)用者需要捕獲或者再拋出;

(4)LockSupport.park()不需要捕獲中斷異?!颈疚挠晒珡奶枴巴缱x源碼”原創(chuàng)】;

(5)Object.wait()不帶超時的,需要另一個線程執(zhí)行notify()來喚醒,但不一定繼續(xù)執(zhí)行后續(xù)內(nèi)容;

(6)LockSupport.park()不帶超時的,需要另一個線程執(zhí)行unpark()來喚醒,一定會繼續(xù)執(zhí)行后續(xù)內(nèi)容;

(7)如果在wait()之前執(zhí)行了notify()會怎樣?拋出IllegalMonitorStateException異常

(8)如果在park()之前執(zhí)行了unpark()會怎樣?線程不會被阻塞,直接跳過park(),繼續(xù)執(zhí)行后續(xù)內(nèi)容;

最后兩點(diǎn)是不是沒想到?!

其實(shí),在《死磕 java線程系列之自己動手寫一個線程池(續(xù))》這篇文章里代碼注釋里稍微提到過unpark()這個方法,它先執(zhí)行,則后續(xù)的park()方法將不再起作用。

park()/unpark()底層的原理是“二元信號量”,你可以把它相像成只有一個許可證的Semaphore,只不過這個信號量在重復(fù)執(zhí)行unpark()的時候也不會再增加許可證,最多只有一個許可證。

關(guān)于信號量的內(nèi)容,可以參考《死磕 java同步系列之Semaphore源碼解析》這篇文章。

LockSupport.park()會釋放鎖資源嗎?

不會,它只負(fù)責(zé)阻塞當(dāng)前線程,釋放鎖資源實(shí)際上是在Condition的await()方法中實(shí)現(xiàn)的。

彩蛋

好了,上面我們交叉對比了Thread.sleep()、Object.wait()、Condition.await()、LockSupport.park()的區(qū)別。

讓我們用一張思維導(dǎo)圖結(jié)束今天的內(nèi)容。

LockSupport.park()是否會釋放鎖資源嗎

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI