LockSupport,構(gòu)建同步組件的基礎(chǔ)工具,幫AQS完成相應(yīng)線程的阻塞或者喚醒的工作。
LockSupport源碼分析
LockSupport定義了一組以park開頭的方法來阻塞當前線程,unpark來喚醒被阻塞的線程。
阻塞線程
- park()實現(xiàn)
public static void park() {
UNSAFE.park(false, 0L);
}
調(diào)用native方法阻塞當前線程。
- parkNanos(long nanos)實現(xiàn)
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
阻塞當前線程,最長不超過nanos納秒,返回條件在park()的基礎(chǔ)上增加了超時返回。
- parkUntil(long deadline)實現(xiàn)
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
阻塞當前線程,知道deadline時間(deadline - 毫秒數(shù))。
在java6之后在park系列方法新增加了入?yún)?code>Object blocker,用于標識阻塞對象,該對象主要用于問題排查和系統(tǒng)監(jiān)控。
- park(Object blocker)實現(xiàn)
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
記錄當前線程等待的對象(阻塞對象);
阻塞當前線程;
當前線程等待對象置為null。
parkNanos(Object blocker, long nanos)實現(xiàn)
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, nanos);
setBlocker(t, null);
}
}
阻塞當前線程,最長等待時間不超過nanos毫秒,同樣,在阻塞當前線程的時候做了記錄當前線程等待的對象操作。
- parkUntil(Object blocker, long deadline)
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(true, deadline);
setBlocker(t, null);
}
阻塞當前線程直到deadline時間,相同的,也做了阻塞前記錄當前線程等待對象的操作。
到這里,問題來了,為什么在java6要在入?yún)⒁隻locker呢?blocker的作用到底是什么?
先看看線程dump的結(jié)果:

從線程dump結(jié)果可以看出:
有blocker的可以傳遞給開發(fā)人員更多的現(xiàn)場信息,可以查看到當前線程的阻塞對象,方便定位問題。所以java6新增加帶blocker入?yún)⒌南盗衟ark方法,替代原有的park方法。
喚醒線程
- unpark(Thread thread)實現(xiàn)
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
喚醒處于阻塞狀態(tài)的線程Thread。
從源碼不難發(fā)現(xiàn),LockSupport所有的方法都是調(diào)用native的park和unpark實現(xiàn)的,接下來我們具體看看HotSpot中的park/unpark的具體實現(xiàn)。
HotSpot里的park/unpark
在HotSpot中,每個java線程都有一個Parker的實例,Parker的定義是這樣子的:

從Parker定義不難看出:
定義私有屬性_counter:可以理解為是否可以調(diào)用park的一個許可證,只有_count > 0的時候才能調(diào)用;
提供public方法park和unpark支撐阻塞/喚醒線程;
-
Parker繼承PlatformParker:
PlatformParker定義
從PlatformParker的定義可以看出,Parker實際上是利用Posix的mutex,condition來實現(xiàn)的。
HotSpot park實現(xiàn)
-
嘗試是否能可以調(diào)用park,如果_counter > 0,可以調(diào)用,將_counter置為0,返回;
park步驟1具體實現(xiàn) -
步驟1不成功,構(gòu)造當前線程的ThreadBlockInVM,檢查_counter > 0是否成立,成立則將_counter設(shè)置為0,unlock mutex,返回;
park步驟2具體實現(xiàn) -
步驟2不成功,根據(jù)等待時間調(diào)用不同的等待函數(shù)等待,如果等待返回正確,將_counter置為0,unlock mutex,返回,park調(diào)用成功。
park步驟3具體實現(xiàn)
相比之下,unpark的實現(xiàn)就簡單多了。
HotSpot unpark實現(xiàn)

- 將_counter置為1;
- 判斷之前_counter的值:
- 小于1時,調(diào)用pthread_cond_signal喚醒在park中等待的線程;
- 等于1時,unlock mutex,返回。
總結(jié):HotSpot Parker用condition和mutex維護了一個_counter變量,park時,變量_counter置為0,unpark時,變量_counter置為1。



