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

park_thread

(手機橫屏看源碼更方便)java


引子

你們知道,我最近在招人,今天遇到個同窗,他的源碼看過一些,而後我就開始了AQS連環問。線程

我:說說AQS的大體流程?code

他:AQS包含一個狀態變量,一個同步隊列……balabala……互斥鎖balabala,共享鎖balabala……blog

我:AQS中除了同步隊列,還有什麼隊列?生命週期

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

我:條件隊列和同步隊列有什麼區別?資源

他:條件隊列balabala,而後調用LockSupport.park()進入休眠,等待被喚醒,……,balabala同步

咦,這時我靈感突發:LockSupport.park()和Thread.sleep()有什麼區別?源碼

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

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

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

我:會嗎?會嗎?會嗎?

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

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

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

首先,咱們先來看看Thread.sleep()和Object.wait()的區別,這是一個爛大街的題目了,你們應該都能說上來兩點。

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

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

(3)Thread.sleep()到時間了會自動喚醒,而後繼續執行;

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

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

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

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

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

其實,這個題目和上面的題目比較相似,由於原本Object.wait()和Condition.await()的原理就比較相似,能夠參考以前彤哥寫的《死磕 java線程系列之線程的生命週期》之篇文章。

這個題目的回答思路跟Object.wait()是基本一致的,不一樣的是Condition.await()底層是調用LockSupport.park()來實現阻塞當前線程的。

實際上,它在阻塞當前線程以前還幹了兩件事,一是把當前線程添加到條件隊列中,二是「徹底」釋放鎖,也就是讓state狀態變量變爲0,而後纔是調用LockSupport.park()阻塞當前線程,能夠參考以前彤哥寫的《死磕 java同步系列之ReentrantLock源碼解析(二)——條件鎖》這篇文章。

看到這裏,今天開篇提的那個問題是否是就有答案了呢【本文由公從號「彤哥讀源碼」原創】?

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

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

(1)從功能上來講,Thread.sleep()和LockSupport.park()方法相似,都是阻塞當前線程的執行,且都不會釋放當前線程佔有的鎖資源

(2)Thread.sleep()無法從外部喚醒,只能本身醒過來;

(3)LockSupport.park()方法能夠被另外一個線程調用LockSupport.unpark()方法喚醒;

(4)Thread.sleep()方法聲明上拋出了InterruptedException中斷異常,因此調用者須要捕獲這個異常或者再拋出;

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

(6)Thread.sleep()自己就是一個native方法;

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

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

兩者都會阻塞當前線程的運行,他們有什麼區別呢?通過上面的分析相信你必定很清楚了,真的嗎?往下看!

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

(2)LockSupport.park()能夠在任意地方執行;

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

(4)LockSupport.park()不須要捕獲中斷異常【本文由公從號「彤哥讀源碼」原創】;

(5)Object.wait()不帶超時的,須要另外一個線程執行notify()來喚醒,但不必定繼續執行後續內容;

(6)LockSupport.park()不帶超時的,須要另外一個線程執行unpark()來喚醒,必定會繼續執行後續內容;

(7)若是在wait()以前執行了notify()會怎樣?拋出IllegalMonitorStateException異常

(8)若是在park()以前執行了unpark()會怎樣?線程不會被阻塞,直接跳過park(),繼續執行後續內容;

最後兩點是否是沒想到?!

其實,在《死磕 java線程系列之本身動手寫一個線程池(續)》這篇文章裏代碼註釋裏稍微提到過unpark()這個方法,它先執行,則後續的park()方法將再也不起做用。

park()/unpark()底層的原理是「二元信號量」,你能夠把它相像成只有一個許可證的Semaphore,只不過這個信號量在重複執行unpark()的時候也不會再增長許可證,最多隻有一個許可證。

關於信號量的內容,能夠參考《死磕 java同步系列之Semaphore源碼解析》這篇文章。

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

不會,它只負責阻塞當前線程,釋放鎖資源其實是在Condition的await()方法中實現的。

彩蛋

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

讓咱們用一張思惟導圖結束今天的內容。

park_thread


歡迎關注個人公衆號「彤哥讀源碼」,查看更多源碼系列文章, 與彤哥一塊兒暢遊源碼的海洋。

qrcode

相關文章
相關標籤/搜索