一、park & unpack demo

main-start 時間Thu May 13 16:17:32 CST 2021 Thread-0 main-end 時間Thu May 13 16:17:33 CST 2021
特點:該方式實現線程的通信不需要鎖,並且可以喚醒指定的線程
Object.wait()、Object.notify() :
- wait和notify都是Object中的方法,在調用這兩個方法前必須先獲得鎖對象,這限制了其使用場合:只能在同步代碼塊中。
- 當對象的等待隊列中有多個線程時,notify只能隨機選擇一個線程喚醒,無法喚醒指定的線程。
二、LockSupport阻塞和喚醒線程原理
LockSupport是通過控制變量_counter來對線程阻塞喚醒進行控制的。原理有點類似於信號量機制。但是_counter的值只有0或者1
當調用park()方法時,會將_counter置為0,同時判斷前值,等於0說明前面被park過,則直接進入排隊,否則將使該線程阻塞。
當調用unpark()方法時,會將_counter置為1,同時判斷前值,小於1會進行線程喚醒,否則直接退出。
形象的理解,線程阻塞需要消耗憑證(permit),這個憑證最多只有1個。當調用park方法時,如果有憑證,則會直接消耗掉這個憑證然后正常退出;但是如果沒有憑證,就必須阻塞等待憑證可用;而unpark則相反,它會增加一個憑證,但憑證最多只能有1個。
為什么可以先喚醒線程后阻塞線程?
因為unpark獲得了一個憑證,之后調用park因為有憑證消費,故不會阻塞。
為什么喚醒兩次后阻塞兩次會阻塞線程。
因為憑證的數量最多為1,連續調用兩次unpark和調用一次unpark效果一樣,只會增加一個憑證;而調用兩次park卻需要消費兩個憑證,但我們有且只有一個憑證。
