本文基于java version "1.8.0_77"
LockSupport(java.util.concurrent.locks.LockSupport)是Java中底層類支竹,提供了基本的線程同步原語嚼锄。JUC中同步框架核心AQS(AbstractQueuedSynchronizer)听哭,就是通過使用LockSupport來實(shí)現(xiàn)線程的阻塞與喚醒的。我們先了解一下LockSupport類,為了解AQS做準(zhǔn)備。
LockSupport中的兩個(gè)核心方法:
- public static void park()
- public static void unpark(Thread thread)
park
譯為“停車”,官方文檔意為:許可壮啊。為了方便理解,在這里我們可以理解為阻塞撑蒜,等待歹啼,掛起
,而unpark
我們理解為喚醒座菠,恢復(fù)
狸眼。
這些字眼是不是很熟悉?我們在使用多線程的時(shí)候會調(diào)用object.wait()
和object.notify()辈灼,object.notifyall()
來達(dá)到等待和喚醒的功能份企。此處我們可以比較著來學(xué)習(xí)。
與object的先wait巡莹,后notify
方法不同的是司志,park與unpark無需擔(dān)心調(diào)用時(shí)序問題,可以先park降宅,后unpark
骂远,也可以先park,后park
腰根。還有一點(diǎn)需要注意激才,多次連續(xù)給一個(gè)線程下發(fā)許可,但是這中間并沒有消耗的情況下额嘿,只會保留一個(gè)許可瘸恼。(可以理解為許可的只有有
或沒有
之分,而沒有數(shù)量的多少)
當(dāng)線程A調(diào)用park()
后册养,會申請一個(gè)許可證:
- 如果沒有許可东帅,會阻塞當(dāng)前線程,直至有其他線程下發(fā)許可(LockSupport.unpark(線程A))球拦。
- 如果此時(shí)已經(jīng)能夠有一個(gè)許可靠闭,則可以繼續(xù)往下執(zhí)行代碼。
我們來看下面的例子:
public static void main(String[] args) {
LockSupport.park();// 獲取許可
System.out.println("END");
}
運(yùn)行上述代碼坎炼,會發(fā)現(xiàn)愧膀,該代碼不會打印END。因?yàn)楫?dāng)前線程申請一個(gè)許可而沒有線程給他許可谣光,故一直阻塞檩淋,進(jìn)程不會關(guān)閉。
多線程中通信的例子:
結(jié)果:
上圖中可以看到萄金,boyThread通過park阻塞線程狼钮,直至girlThread調(diào)用unpark喚醒碳柱。
看一個(gè)特殊例子:
結(jié)果:
可以看到,即便是已經(jīng)下發(fā)了4個(gè)許可熬芜,但是實(shí)際上只有一個(gè)許可,也就是說許可存在的個(gè)數(shù)只有0或1福稳。
其他方法:
-
void park(Object blocker)
阻塞線程時(shí)添加附加信息涎拉,用來記錄線程是被誰堵塞的,程序出現(xiàn)問題時(shí)候的圆,通過線程監(jiān)控分析工具可以找出問題所鼓拧。 -
void parkNanos(long nanos)
參數(shù)為阻塞超時(shí)時(shí)間,超時(shí)時(shí)間過后越妈,如果還沒有下發(fā)許可季俩,則自動喚醒 -
void parkNanos(Object blocker, long nanos)
同上,方法重載 -
void parkUntil(long deadline)
參數(shù)為阻塞截止時(shí)間梅掠,為絕對時(shí)間酌住,到達(dá)時(shí)間后,如果還沒有下發(fā)許可阎抒,則自動喚醒 -
void parkUntil(Object blocker, long deadline)
同上酪我,方法重載
與Object中wait和notify的區(qū)別
- 比wait/notify更加輕便靈活。LockSupport直接操作線程且叁,而wait/notify則是需要一個(gè)Object對線程進(jìn)行操作都哭。
- 不依賴監(jiān)視器(鎖)。wait/notify需要在synchronized中進(jìn)行調(diào)用逞带,它首先需要獲取到鎖欺矫,才能進(jìn)行下面的操作。而LockSupport則是直接進(jìn)行調(diào)用展氓。(synchronized與wait/notify配合使用穆趴,ReentrantLock與Condition配合使用。而Condition就是使用LockSupport實(shí)現(xiàn)等待與喚醒的)
End