1. 概述
LockSupport蝙寨,構(gòu)建同步組件的基本工具,幫AQS完成相應(yīng)線程的阻塞或者喚醒的工作磷斧。
2. 主要方法
主要介紹LockSupport類的park()和unpark()方法崖堤。
從源碼中我們不難看出,這兩個方法底層都是通過Unsafe類來實現(xiàn)的柠并。
// 暫停當前線程
public static void park() {
UNSAFE.park(false, 0L);
}
// 恢復(fù)某個線程的運行
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
與Object類的wait()岭接、notify()、notifyAll()相比臼予,park()和unpark()又有哪些特點:
- wait鸣戴、notify、notifyAll必須配合Object Monitor一起來使用粘拾,而park窄锅、unpark不需要
- park & unpark是以線程為單位來阻塞和喚醒線程,而notify只能隨機喚醒一個等待線程缰雇,notifyAll是喚醒所有等待線程入偷,就不那么精確
- park & unpark可以先unpark追驴,而wait & notify不能先notify
- 多次unpark不能疊加,多次unpark只需一次park就可抵消掉
3. 底層原理
每個線程都有自己的一個Parker對象疏之,由三部分組成_counter殿雪,_cond和_mutex。
_counter可以理解為是否可以調(diào)用park的一個許可證体捏,只有_count > 0的時候才能調(diào)用冠摄。
_cond可以理解為一個條件變量。
_mutex可以理解為一個互斥鎖几缭。
-
Unsafe.park()
- 當前線程調(diào)用Unsafe.park()方法
- 判斷_counter河泳,本情況為0,這時年栓,獲取_mutex互斥鎖
- 線程進入_cond條件變量阻塞
- 設(shè)置_counter為0
-
Unsafe.unpark()
- 調(diào)用Unsafe.unpark(Thread_0)方法拆挥,設(shè)置_counter值為1
- 喚醒_cond條件變量中的線程Thread_0
- Thread_0恢復(fù)運行
- 設(shè)置_counter為0
-
先Unsafe.unpark(),后Unsafe.park()
- 調(diào)用Unsafe.unpark(Thread_0)方法某抓,設(shè)置_counter值為1
- 當前線程調(diào)用Unsafe.park()方法
- 檢查_counter纸兔,本情況為1,這時線程無需阻塞否副,繼續(xù)運行
- 設(shè)置_counter為0