這天,我還在安詳的看書學習,學妹突然找我,問到:好學長,你懂 Condition 介面嘛?能教教我嘛?

看到學妹來了,我立馬也精神了起來,說到:

Condition就是實作了管程里面的條件變數,
Java 語言內置的管程里只有一個條件變數,而Lock&Condition實作的管程支持多個條件變數,
因為支持多個條件變數,能讓代碼可讀性更好,實作也更容易,
例如,你看我這里實作一個阻塞佇列,就需要兩個條件變數,
可愛的學妹,又真誠發問到:那如何利用兩個條件變數實作阻塞佇列呢?
一個阻塞佇列,需要兩個條件變數:
- 佇列不空(空佇列不可出隊)
- 佇列不滿(佇列已滿不可入隊)

Lock和Condition實作的管程,執行緒等待和通知需要呼叫await()、signal()、signalAll(),它們的語意和wait()、notify()、notifyAll()相同,
- Lock&Condition實作的管程里只能使用await()、signal()、signalAll()
- synchronized實作的管程才能使用wait()、notify()、notifyAll()
如果在Lock&Condition實作的管程里呼叫wait()、notify()、notifyAll(),你距離離職就更近一步,
JDK的Lock和Condition不過就是管程的一種實作,看看在Dubbo中,Lock和Condition是怎么用的,
我們先要清楚,什么是同步與異步呢?
- 同步
呼叫方需要等待結果 - 異步
不需要等待結果
那代碼里如何實作異步呢?
- 呼叫方創建一個子執行緒,在子執行緒中執行方法呼叫,即異步呼叫
- 方法實作時,創建一個新的執行緒執行主要邏輯,主執行緒直接return,即異步方法,
異步場景挺多,比如TCP協議本身是異步的,日常的RPC呼叫,在TCP協議層面,發送完RPC請求后,執行緒不會等待RPC回應結果,
是不是好奇了,明明日常使用的RPC呼叫都是同步的呀?這到底是同步還是異步?
很好想象,肯定有人幫忙實作了異步轉同步,比如RPC框架Dubbo,具體它是怎么做到的呢?
對于下面一個簡單的RPC呼叫,默認情況下sayHello()是個同步方法,即執行service.sayHello(“dubbo”)時,執行緒會停下來等結果,
DemoService service = 初始化部分省略
String message = service.sayHello("dubbo");
System.out.println(message);
- 若此時dump呼叫執行緒的呼叫堆疊

發現呼叫執行緒阻塞了,執行緒狀態是TIMED_WAITING,本來發送請求是異步的,但是呼叫執行緒卻阻塞了,說明Dubbo幫我們做了異步轉同步的事情,通過呼叫堆疊看到執行緒是阻塞在DefaultFuture.get(),所以Dubbo異步轉同步的功能應該是通過DefaultFuture實作,
DefaultFuture.get()之前發生了什么呢:

我們的期望:
- RPC回傳結果前,阻塞呼叫執行緒,讓呼叫執行緒等待
- RPC回傳結果后,喚醒呼叫執行緒,讓呼叫執行緒重新執行
這就是經典的等待-通知機制,也就想到了管程的實作方案,看看遠古版本的Dubbo是怎么實作的,

好了,下課!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/279305.html
標籤:其他
