【多執行緒】LockSupport的執行緒等待喚醒機制
阿新 • • 發佈:2021-02-07
技術標籤:多執行緒
前言:
傳統的執行緒等待喚醒機制有兩種方式分別是synchronized(wait和notify)和JUC包中的顯示鎖Lock(condition的await()方法和signal()方法),但是這兩個方式有兩個缺點,分別是都不能脫離synchronized,和lock、unlock,如果脫離就會報錯,還有就是wait和notify,await和signal的執行順序要固定,必須先wait然後在notify,否則會導致程式無法結束。
所以出現第三種方式,那就是LockSupport(park和unpark),LockSupport類可以阻塞當前執行緒以及喚醒指定被阻塞的執行緒。接下來詳細介紹。
1、LockSupport介紹
- LockSupport是用來建立鎖和其他同步類的基本執行緒阻塞原語
- LockSupport類使用了一種名為Permit(許可)的概念來做到阻塞和喚醒執行緒的功能,每個執行緒都有一個許可(Permit),Permit只有兩個值1和0,預設是0。
- 把許可看成是一種(0,1)訊號量(Semaphore),但是與Semaphore不同的是,許可的累加上限是1.
- 兩個方法
park()/park(Object blocker):阻塞當前執行緒/阻塞傳入的具體執行緒
unpark(Thread thread):喚醒處於阻塞狀態的指定執行緒 - 呼叫一次unpark就加1 ,最大就是1
- 呼叫一次park會消費permit,也就是將1變成0,同時park立即返回。如果再次用park就會阻塞,這時呼叫unpark會把permit置為1
- 每個執行緒都有一個相關的permit,permit最多隻有一個,重複呼叫unpark也不會累計憑證
2、程式碼驗證
public static void main(String[] args) {
Thread a = new Thread(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System. out.println(Thread.currentThread().getName() + "\t" + "-----come in " + System.currentTimeMillis());
LockSupport.park(); // 被阻塞....等待通知,他需要通過許可證
System.out.println(Thread.currentThread().getName() + "\t" + "-----被 喚 醒 " + System.currentTimeMillis());
}, "a");
a.start();
Thread b = new Thread(() -> {
LockSupport.unpark(a);
System.out.println(Thread.currentThread().getName() + "\t" + "-----通知了");
}, "b");
b.start();
}
執行結果:
首先 park和unpark 不需要鎖塊, 其次根據上面的結果我們看出 先unpark(喚醒)後park(等待)也同樣支援