【vert.x準備篇1】同步和異步,阻塞和非阻塞概念澄清

爲了能更好的理解vert.x的線程模型,我們必須要先明確幾個概念:同步(Synchronous)和異步(Asynchronous),阻塞(Blocking)和非阻塞(Non-Blocking)。關於這幾個名詞的解釋網絡上也是衆多紛紜,每個人說法都不太一樣,但說的又似乎很有道理。其實造成這種情況的最主要原因是這四個概念並不是完全隔離、互斥的,而是相互之間有重疊。例如,當提到異步時那調用一定是非阻塞的,提到同步時則一定會有阻塞調用,此謂之重疊;然而如果我們在談異步,那在調用方的角度來看是一定不存在阻塞的情況發生的,此謂之互斥。下面我們詳細聊聊對於這幾個名詞大家應該如何理解。

我們以在單線程環境下調用功能爲讀取文件內容的方法readFile(filename)爲例來模擬一下都會發生什麼:

  • 阻塞

調用此方法後主線程進入阻塞狀態,期間不能執行任務操作,一直到readFile()返回才能繼續執行後面的代碼。

  • 非阻塞

調用此方法後,readFile()立刻返回,主線程可以繼續執行後面的代碼而不需要等待磁盤I/O操作完成。但這裏會產生一個問題,主線程怎麼才能知道readFile()是否完成?是會有人通知這一事件,還是主線程主動去輪詢呢?

  • 同步

其實同步/異步是一個比阻塞/非阻塞更加廣泛的概念。我們在說阻塞時,一定是在描述某種I/O操作,比如文件讀寫和網絡收發。而對於同/異步來說則可以用來描述更多的行爲,比如對於HTTP協議來說,請求方發起請求後必須要一直等待,直到收到響應才能再次發起其他請求,這就是一種同步,即需要等待你要做的事完成才能繼續後面的事。對於readFile()的調用來說,同步則是指主線程必須等待readFile()返回(即幹完了事)才能繼續執行後面的代碼,這點跟阻塞是完全相同的。也就是說,當我們描述一個方法是同步調用時,則也是在描述這同時也是一個阻塞調用。

可能有朋友會提及一種"同步非阻塞"的概念,即調用readFile()時會馬上返回,此爲非阻塞,但是後續還需要主線程停止執行其他代碼來主動去查詢此方法是否完成,此爲同步。其實這種說法也是對的,因爲上面說過了,同步是一種寬泛的概念,對於這種場景來說,無論"查詢"動作是阻塞的還是死循環在查,對於主線程來說它其實是沒有機會幹其他事的,即無法執行後面的代碼,這其實就是廣義上的同步。

  • 異步

我們在描述某個方法是異步的時候,其實同時也是在描述這個方法是非阻塞的,這是二者概念上的相同之處。前面在討論非阻塞時拋出了一個關於調用方到底如何獲悉readFile()是否完成的問題,這裏就可以回答了。在編程領域,異步除了是在表明方法調用爲非阻塞外,也是在暗示調用方並不需要主動查詢任務完成情況,而是會"被動"通知。而發起這個通知的"人",往往是操作系統,即操作系統會通過某種方式通知進程,告訴它你所關心的I/O操作已經完成了。爲什麼用往往呢,還是那句話,異步是一個廣泛的概念,除了操作系統 ,我們也可以在用戶進程中自己實現這種通知。也就是說誰通知的並不重要,重要的是調用方並不需要主動查詢

總結,同步和異步,阻塞和非阻塞這4個概念是相互交叉的,它們既有區別,也有重疊之處。其中,同步更強調調用方需要主動查詢子任務是否完成,而異步則強調調用方會被動的收到子任務完成的通知,此期間調用方都可以繼續執行其他代碼。

下一篇會講解reactor(反應堆)線程模型的相關知識。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章