多線程編發(fā)編程6-LockSupport源碼剖析

? ? 今天來(lái)說(shuō)一說(shuō)LockSupport類,為什么要說(shuō)該類呢?因?yàn)檫@LockSupport類是鎖和同步類的基礎(chǔ),它提供線程的掛起和喚醒。其實(shí)從源碼中也可以看到LockSupport只是多Unsafe類的park系列方法和unpark系列方法進(jìn)行了一層淺淺的封裝。

? ? LockSupport類與每個(gè)使用它的線程都會(huì)關(guān)聯(lián)一個(gè)許可證,在默認(rèn)情況下調(diào)用LockSupport類方法的線程是不持有許可證的。

? ? 下面通過(guò)源碼來(lái)解釋幾個(gè)主要的方法吧。

park()

public static void park() {

UNSAFE.park(false, 0L);

}

????park方法調(diào)用的是Unsafe類的park方法,如果調(diào)用park方法的線程已經(jīng)拿到了與LockSupport關(guān)聯(lián)的許可證,則調(diào)用park方法會(huì)立即返回,否則會(huì)被掛起阻塞。阻塞的線程會(huì)一直阻塞直到下面三個(gè)條件其中之一發(fā)生:

1)當(dāng)其他線程調(diào)用了unpark方法并把當(dāng)前阻塞線程作為參數(shù)傳入,喚醒當(dāng)前阻塞線程。

2)當(dāng)其他線程調(diào)用了阻塞線程的interrupte方法。

3)當(dāng)發(fā)生無(wú)理由的虛假喚醒。

? ? 從上面的源碼可以看到park方法返回并不會(huì)返回任何值,所以調(diào)用該方法者在調(diào)用park方法返回之后需要再對(duì)條件進(jìn)行判斷。

park(Object blocker)

public static void park(Object blocker) {

Thread t = Thread.currentThread();

? ? setBlocker(t, blocker);

? ? UNSAFE.park(false, 0L);

? ? setBlocker(t, null);

}

? ? 和park()方法一樣,調(diào)用的是Unsafe類的park方法,如果調(diào)用park方法的線程已經(jīng)拿到了與LockSupport關(guān)聯(lián)的許可證,則調(diào)用park方法會(huì)立即返回,否則會(huì)被掛起阻塞。不同點(diǎn)在于park(Object blocker)方法傳遞一個(gè)blocker變量,在線程阻塞前會(huì)將blocker變量賦值給當(dāng)前線程的本地變量parkBlocker,UNSAFE.park返回之后,再重新將當(dāng)前線程的本地變量parkBlocker設(shè)置為null。

? ? 設(shè)置blocker變量有什么用呢?可以通過(guò)getBlocker(Thread t)方法獲得是哪個(gè)對(duì)象調(diào)用了park方法阻塞了當(dāng)前線程,可以幫助對(duì)堆棧進(jìn)行分析。

? ? 關(guān)于LockSupport中帶時(shí)間的park方法就在這一句帶過(guò)了,parkNanos(long nanos)阻塞nanos秒后返回,相對(duì)時(shí)間,parkUntil(long deadline)阻塞直到deadline時(shí)間為止,絕對(duì)時(shí)間。

unpark(Thread thread)

public static void unpark(Thread thread) {

if (thread !=null)

UNSAFE.unpark(thread);

}

? ? 為指定的線程獲得許可證,在獲得許可證之前如果當(dāng)前線程阻塞,則獲得許可證之后會(huì)被喚醒返回。如果參數(shù)中的線程已經(jīng)獲得過(guò)許可證了,則不會(huì)再次獲得。

? ? 下面看兩個(gè)例子:

例一:

LockSupport.unpark(Thread.currentThread());

LockSupport.park(Thread.currentThread());

? ? 當(dāng)前線程會(huì)在調(diào)用park方法立馬返回,因?yàn)楫?dāng)前線程在調(diào)用park之前調(diào)用了unpark返回獲得了許可證。

例二:

LockSupport.unpark(Thread.currentThread());

LockSupport.unpark(Thread.currentThread());

LockSupport.park(Thread.currentThread());

LockSupport.park(Thread.currentThread());

? ? 當(dāng)前線程會(huì)被阻塞在第二個(gè)park方法,雖然在調(diào)用park方法之前調(diào)用了兩次unpark,但是許可證不能疊加,所以當(dāng)前線程只獲得了一個(gè)許可證,而在第一次調(diào)用park方法的時(shí)候已經(jīng)消耗掉該許可證,所以在第二次調(diào)用park方法已沒(méi)有許可證,則會(huì)被掛起阻塞。

? ? LockSupport類是之后講解鎖和其他同步類的底層實(shí)現(xiàn),所以理解LockSupport類對(duì)之后的理解鎖以及同步類是有幫助的。? ?

? ? 今天的分享就到這,有看不明白的地方一定是我寫的不夠清楚,所有歡迎提任何問(wèn)題以及改善方法。

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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