1。分清非同步/同步,阻塞/非阻塞。

首先講下個人對非同步和同步,阻塞和非阻塞的概念的理解。

關於這個概念看了許多解釋,都是似是而非,並不能完全get到點。個人認為從程序間通訊的角度理解比較好,在《作業系統》中關於的部分是這樣解釋的:

程序間的通訊時透過 send() 和 receive() 兩種基本操作完成的。具體如何實現這兩種基礎操作,存在著不同的設計。

訊息的傳遞有可能是阻塞的或非阻塞的 – 也被稱為同步或非同步的:

阻塞式傳送(blocking send)。 傳送方程序會被一直阻塞, 直到訊息被接受方程序收到。

非阻塞式傳送(nonblocking send)。 傳送方程序呼叫 send() 後, 立即就可以其他操作。

阻塞式接收(blocking receive) 接收方呼叫 receive() 後一直阻塞, 直到訊息到達可用。

非阻塞式接受(nonblocking receive) 接收方呼叫 receive() 函式後, 要麼得到一個有效的結果, 要麼得到一個空值, 即不會被阻塞。

上述不同型別的傳送方式和不同型別的接收方式,可以自由組合。也就是說,阻塞和非阻塞可以理解為是傳送方的行為,同步和非同步是接收方的行為。舉個例子:

我們現在去在一條步行街上的銀行辦理業務,根據場景可以解釋為以下多種情況:

拿到號後,自己是一直在等候區等待(阻塞),還是出去逛街,時不時回來確認一下(非阻塞)。

輪到我們辦理業務的時候,是我們自己確認輪到自己了(同步),還是銀行會通知我們去辦理業務(非同步)。

2。非同步呼叫的原理

如果我們使用一個非同步呼叫方法的時候,可以理解為,傳送完請求後,我們就可以繼續去做自己的事情,然後在一個合適的節點去取資料即可。這裡需要明確,是誰幫我們把這些事情做完的。一般,有兩種情況:

第一種情況,本地IO操作時,可以透過DMA功能實現,在呼叫DMA傳輸資料的時候,CPU是不需要執行處理的,只需要發起傳輸和等待傳輸即可,也就是說,在這段時間裡,CPU可以乾點別的事情。DMA的英文拼寫是“Direct Memory Access”,漢語的意思就是直接記憶體訪問。DMA既可以指記憶體和外設直接存取資料這種記憶體訪問的計算機技術,又可以指實現該技術的硬體模組(對於通用計算機PC而言,DMA控制邏輯由CPU和DMA控制介面邏輯晶片共同組成,嵌入式系統的DMA控制器內建在處理器晶片內部,一般稱為DMA控制器,DMAC)。

第二種情況,透過多執行緒實現,主執行緒發起請求操作(這裡用執行緒解釋,多程序也是可以的),系統選取一個執行緒接過這個主執行緒的請求任務,然後當非同步呼叫完成後,系統會從可用執行緒中選取一個執行緒執行回撥函式,將結果推回給主執行緒。這裡的非同步呼叫,主要是為了讓呼叫方法的主執行緒不需要同步等待在這個函式呼叫上,從而可以讓主執行緒繼續執行它下面的程式碼。

關於第二種情況,實現的核心思路在於:

其他執行緒/程序執行IO操作,讓發起請求方可以不用等待。

在執行完非同步呼叫後,通知呼叫者提取相關資料(這裡可以使用註冊回撥函式的辦法)。

3。RPC中的非同步呼叫

RPC框架中,非同步請求是一個很重要的方法。一般,在RPC框架中,如果我們使用同步呼叫,在發起請求後,只能等待結果,中間不能去幹其他的事情。我們也稱這種模式為請求-響應模式。這個模式優點在於時序清晰,邏輯簡單,缺點也顯而易見,大量的CPU時間會阻塞在等待請求的響應上,另外,也會存在只能由客戶端向服務端傳送請求,而服務端無法主動向客戶端傳送事件通知,也就是缺乏callback機制。

在RPC框架中,一個比較通用的非同步呼叫方法,是在雙向會話式的基礎上,讓呼叫方透過註冊回撥函式來獲得請求結果實現。雙向會話式通訊機制透過去掉請求的返回值,所有的方法請求都定義為無返回結果,呼叫方在發出請求之後就可以繼續幹後面的事情了,而不需要再等待服務返回結果。同時針對服務介面定義一個Callback介面用於服務端向客戶端傳送請求結果和事件通知,透過回撥函式,伺服器就可以主動向客戶端傳送訊息,將訊息推回給請求方。

以上,就是對非同步呼叫的個人理解過程,從基本概念到如何實現,僅記錄下來,方便檢視。