1. 程式人生 > 其它 >【多執行緒】LockSupport的執行緒等待喚醒機制

【多執行緒】LockSupport的執行緒等待喚醒機制

技術標籤:多執行緒

前言:

傳統的執行緒等待喚醒機制有兩種方式分別是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(等待)也同樣支援