LockSupport都不知道,怎么拿offer?

LockSupport是一個(gè)編程工具類(lèi),主要是為了阻塞和喚醒線(xiàn)程用的。使用它我們可以實(shí)現(xiàn)很多功能,今天主要就是對(duì)這個(gè)工具類(lèi)的講解,希望對(duì)你有幫助:

一、LockSupport簡(jiǎn)介

1、LockSupport是什么

剛剛開(kāi)頭提到過(guò),LockSupport是一個(gè)線(xiàn)程工具類(lèi),所有的方法都是靜態(tài)方法,可以讓線(xiàn)程在任意位置阻塞,也可以在任意位置喚醒。

它的內(nèi)部其實(shí)兩類(lèi)主要的方法:park(停車(chē)阻塞線(xiàn)程)和unpark(啟動(dòng)喚醒線(xiàn)程)。

image

注意上面的123方法,都有一個(gè)blocker,這個(gè)blocker是用來(lái)記錄線(xiàn)程被阻塞時(shí)被誰(shuí)阻塞的。用于線(xiàn)程監(jiān)控和分析工具來(lái)定位原因的。

現(xiàn)在我們知道了LockSupport是用來(lái)阻塞和喚醒線(xiàn)程的,而且之前相信我們都知道wait/notify也是用來(lái)阻塞和喚醒線(xiàn)程的,那么它相比,LockSupport有什么優(yōu)點(diǎn)呢?

2、與wait/notify對(duì)比

這里假設(shè)你已經(jīng)了解了wait/notify的機(jī)制,如果不了解,可以在網(wǎng)上一搜,很簡(jiǎn)單。相信你既然學(xué)到了這個(gè)LockSupport,相信你已經(jīng)提前已經(jīng)學(xué)了wait/notify。

我們先來(lái)舉一個(gè)使用案例:

image

上面這段代碼的意思是,我們定義一個(gè)線(xiàn)程,但是在內(nèi)部進(jìn)行了park,因此需要unpark才能喚醒繼續(xù)執(zhí)行,不過(guò)上面,我們?cè)贛yThread進(jìn)行的park,在main線(xiàn)程進(jìn)行的unpark。

這樣來(lái)看,好像和wait/notify沒(méi)有什么區(qū)別。那他的區(qū)別到底是什么呢?這個(gè)就需要仔細(xì)的觀察了。這里主要有兩點(diǎn):

(1)wait和notify都是Object中的方法,在調(diào)用這兩個(gè)方法前必須先獲得鎖對(duì)象,但是park不需要獲取某個(gè)對(duì)象的鎖就可以鎖住線(xiàn)程。

(2)notify只能隨機(jī)選擇一個(gè)線(xiàn)程喚醒,無(wú)法喚醒指定的線(xiàn)程,unpark卻可以喚醒一個(gè)指定的線(xiàn)程。

區(qū)別就是這倆,還是主要從park和unpark的角度來(lái)解釋的。既然這個(gè)LockSupport這么強(qiáng),我們就深入一下他的源碼看看。

二、源碼分析(基于jdk1.8)

1、park方法

image

blocker是用來(lái)記錄線(xiàn)程被阻塞時(shí)被誰(shuí)阻塞的。用于線(xiàn)程監(jiān)控和分析工具來(lái)定位原因的。setBlocker(t, blocker)方法的作用是記錄t線(xiàn)程是被broker阻塞的。因此我們只關(guān)注最核心的方法,也就是UNSAFE.park(false, 0L)。

UNSAFE是一個(gè)非常強(qiáng)大的類(lèi),他的的操作是基于底層的,也就是可以直接操作內(nèi)存,因此我們從JVM的角度來(lái)分析一下:

每個(gè)java線(xiàn)程都有一個(gè)Parker實(shí)例:

image

我們換一種角度來(lái)理解一下park和unpark,可以想一下,unpark其實(shí)就相當(dāng)于一個(gè)許可,告訴特定線(xiàn)程你可以停車(chē),特定線(xiàn)程想要park停車(chē)的時(shí)候一看到有許可,就可以立馬停車(chē)?yán)^續(xù)運(yùn)行了。因此其執(zhí)行順序可以顛倒。

現(xiàn)在有了這個(gè)概念,我們體會(huì)一下上面JVM層面park的方法,這里面counter字段,就是用來(lái)記錄所謂的“許可”的。

本文部分總結(jié)來(lái)源于:http://www.itdecent.cn/p/1f16b838ccd8

當(dāng)調(diào)用park時(shí),先嘗試直接能否直接拿到“許可”,即_counter>0時(shí),如果成功,則把_counter設(shè)置為0,并返回。

image

如果不成功,則構(gòu)造一個(gè)ThreadBlockInVM,然后檢查_(kāi)counter是不是>0,如果是,則把_counter設(shè)置為0,unlock mutex并返回:

image

否則,再判斷等待的時(shí)間,然后再調(diào)用pthread_cond_wait函數(shù)等待,如果等待返回,則把_counter設(shè)置為0,unlock mutex并返回:

image

這就是整個(gè)park的過(guò)程,總結(jié)來(lái)說(shuō)就是消耗“許可”的過(guò)程。

2、unpark

還是先來(lái)看一下JDK源碼:

image

上面注釋的意思是給線(xiàn)程生產(chǎn)許可證。

當(dāng)unpark時(shí),則簡(jiǎn)單多了,直接設(shè)置_counter為1,再u(mài)nlock mutext返回。如果_counter之前的值是0,則還要調(diào)用pthread_cond_signal喚醒在park中等待的線(xiàn)程:

image

ok,現(xiàn)在我們已經(jīng)對(duì)源碼進(jìn)行了分析,整個(gè)過(guò)程其實(shí)就是生產(chǎn)許可和消費(fèi)許可的過(guò)程。而且這個(gè)生產(chǎn)過(guò)程可以反過(guò)來(lái)。也就是先生產(chǎn)再消費(fèi)。下面我們使用幾個(gè)例子驗(yàn)證一波。

三、LockSupport使用

1、先interrupt再park

image

我們看一下結(jié)果:

image

2、先unpark再park

image

我們只需在park之前先休眠1秒鐘,這樣可以確保unpark先執(zhí)行。

image

OK,今天的文章先寫(xiě)到這,如有問(wèn)題,還請(qǐng)批評(píng)指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容