阻塞和非阻塞,同步和異步 總結

阻塞和非阻塞,同步和異步

1 例子

故事:老王燒開水。

出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。

老王想了想,有好幾種等待方式

1.老王用水壺煮水,並且站在那裏不管水開沒開,每隔一定時間看看水開了沒。-同步阻塞

老王想了想,這種方法不夠聰明。

2.老王還是用水壺煮水,不再傻傻的站在那裏看水開,跑去寢室上網但是還是會每隔一段時間過來看看水開了沒有,水沒有開就走人。-同步非阻塞

老王想了想,現在的方法聰明瞭些,但是還是不夠好。

3.老王這次使用高大上的響水壺來煮水,站在那裏但是不會再每隔一段時間去看水開,而是等水開了,水壺會自動的通知他。-異步阻塞

老王想了想,不會呀,既然水壺可以通知我,那我爲什麼還要傻傻的站在那裏等呢,嗯,得換個方法。

4.老王還是使用響水壺煮水,跑到客廳上網去,等着響水壺自己把水煮熟了以後通知他。-異步非阻塞

老王豁然,這下感覺輕鬆了很多。


  • 同步和異步

    同步就是燒開水,需要自己去輪詢(每隔一段時間去看看水開了沒),異步就是水開了,然後水壺會通知你水已經開了,你可以回來處理這些開水了。
    同步和異步是相對於操作結果來說,會不會等待結果返回。

  • 阻塞和非阻塞

    阻塞就是說在煮水的過程中,你不可以去幹其他的事情,非阻塞就是在同樣的情況下,可以同時去幹其他的事情。阻塞和非阻塞是相對於線程是否被阻塞。

其實,這兩者存在本質的區別,它們的修飾對象是不同的。阻塞和非阻塞是指進程訪問的數據如果尚未就緒,進程是否需要等待,簡單說這相當於函數內部的實現區別,也就是未就緒時是直接返回還是等待就緒。
而同步和異步是指訪問數據的機制,同步一般指主動請求並等待I/O操作完畢的方式,當數據就緒後在讀寫的時候必須阻塞,異步則指主動請求數據後便可以繼續處理其它任務,隨後等待I/O,操作完畢的通知,這可以使進程在數據讀寫時也不阻塞。

2 詳細介紹

網絡IO的模型大致包括下面幾種

  • 同步模型(synchronous IO)

    • 阻塞IO(bloking IO)

    • 非阻塞IO(non-blocking IO)

    • 多路複用IO(multiplexing IO)

    • 信號驅動式IO(signal-driven IO)

  • 異步IO(asynchronous IO)

    • 異步IO

網絡IO的本質是socket的讀取,socket在linux系統被抽象爲流,IO可以理解爲對流的操作。對於一次IO訪問,數據會先被拷貝到操作系統內核的緩衝區中,然後纔會從操作系統內核的緩衝區拷貝到應用程序的地址空間,所以一般會經歷兩個階段:

  1. 等待所有數據都準備好或者一直在等待數據,有數據的時候將數據拷貝到系統內核;

  2. 將內核緩存中數據拷貝到用戶進程中;

對於socket流而言:

  1. 等待網絡上的數據分組到達,然後被複制到內核的某個緩衝區;

  2. 把數據從內核緩衝區複製到應用進程緩衝區中;

2.1 阻塞IO

2.1.1 介紹

這也是最常用的模型,默認情況下所有的套接字都是 阻塞 的;

26414081-file_1491994457423_13e6d.png

我們把recvfrom函數視爲系統調用,因爲我們正區分進程和內核,系統調用一般都會從在應用進程空間中運行切換到內核空間中運行,一段時間後又再切換回來;

我們可以從圖中看到,應用進程從 進行系統調用 到 複製數據報到應用進程的緩衝區完成 的整段時間內是被阻塞的;在這個過程中,要麼正確到達,要麼系統調用被信號打斷;直到數據報被複制到用戶進程完成後,用戶進程才解除阻塞的狀態,當然,這是用戶進程自己進行的阻塞;

2.1.2 優點和缺點

  • 優點:能夠及時返回數據,無延遲;方便調試;

  • 缺點:需要付出等待的代價;

2.2 非阻塞IO

2.2.1 介紹

非阻塞,當所請求的I/O操作非得把當前進程設置成睡眠才能完成時,不要把當前進程設置成睡眠,而是返回一個錯誤信息(數據報沒有準備好的情況下),此時當前進程可以做其它的事情,不用阻塞;

27967427-file_1491997152954_10575.png

從圖中可以得知,前三次系統調用時都沒有數據可以返回,內核均返回一個 EWOULDBLOCK,並且不會阻塞當前進程,直到第四次詢問內核緩衝區是否有數據的時候,此時內核緩衝區中已經有一個準備好的數據,因此將內核數據複製到用戶空間,此時系統調用則返回成功;

當一個應用進程像這樣對一個非阻塞socket循環調用 recv/recvfrom 時,則稱爲輪詢;應用進程持續輪詢內核,以查看某個操作是否就緒,這麼做往往消耗大量的CPU時間。

2.2.2 優點和缺點

  • 優點:相較於阻塞模型,非阻塞不用再等待任務,而是把時間花費到其它任務上,也就是這個當前線程同時處理多個任務;

  • 缺點:導致任務完成的響應延遲增大了,因爲每隔一段時間纔去執行詢問的動作,但是任務可能在兩個詢問動作的時間間隔內完成,這會導致整體數據吞吐量的降低。

2.3 IO多路複用

2.3.1 介紹

有了I/O複用,我們就可以調用 select或poll,讓其阻塞在兩個系統調用(1.詢問數據是否準備好並且直到數據準備好才返回;2.內核是否把數據全部複製完成到用戶進程)中的某一個之上

2193057-file_1491998838696_160a3.png

圖中阻塞於 select 調用,等待數據報套接字變爲可讀。當select返回套接字可讀這一條件的時候,則調用 recvfrom 把所讀數據報復制到應用進程緩衝區;

之前的同步非阻塞方式需要用戶進程不停的輪詢,但是IO多路複用不需要不停的輪詢,而是派別人去幫忙循環查詢多個任務的完成狀態,UNIX/Linux 下的 select、poll、epoll 就是幹這個的;select調用是內核級別的,select輪詢相對非阻塞的輪詢的區別在於---前者可以等待多個socket,能實現同時對多個IO端口進行監聽,當其中任何一個socket的數據準好了,就能返回進行可讀,然後進程再進行recvform系統調用,將數據由內核拷貝到用戶進程,當然這個過程是阻塞的。select或poll調用之後,會阻塞進程,與blocking IO阻塞不同在於,此時的select不是等到socket數據全部到達再處理, 而是有了一部分數據(網絡上的數據是分組到達的)就會調用用戶進程來處理。如何知道有一部分數據到達了呢?監視的事情交給了內核,內核負責數據到達的處理。

我認爲上面那句話中存在兩個重要點:1.對多個socket進行監聽,只要任何一個socket數據準備好就返回可讀;2.不等一個socket數據全部到達再處理,而是一部分socket的數據到達了就通知用戶進程;

其實 select、poll、epoll 的原理就是不斷的遍歷所負責的所有的socket完成狀態,當某個socket有數據到達了,就返回可讀並通知用戶進程來處理;

2.3.2 優點和缺點

  • 優點:能夠同時處理多個連接,系統開銷小,系統不需要創建新的額外進程或者線程,也不需要維護這些進程和線程的運行,降低了系統的維護工作量,節省了系統資源。

  • 缺點:如果處理的連結數目不高的話,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延遲還更大。(因爲阻塞可以保證沒有延遲,但是多路複用是處理先存在的數據,所以數據的順序則不管,導致處理一個完整的任務的時間上有延遲)

2.3.3 同步非阻塞和多線程+同步阻塞

高併發的程序一般使用同步非阻塞方式而非多線程 + 同步阻塞方式。要理解這一點,首先要扯到併發和並行的區別。比如去某部門辦事需要依次去幾個窗口,辦事大廳裏的人數就是併發數,而窗口個數就是並行度。也就是說併發數是指同時進行的任務數(如同時服務的 HTTP 請求),而並行數是可以同時工作的物理資源數量(如 CPU 核數)。通過合理調度任務的不同階段,併發數可以遠遠大於並行度,這就是區區幾個 CPU 可以支持上萬個用戶併發請求的奧祕。在這種高併發的情況下,爲每個任務(用戶請求)創建一個進程或線程的開銷非常大。而同步非阻塞方式可以把多個 IO 請求丟到後臺去,這就可以在一個進程裏服務大量的併發 IO 請求。

2.4 信號驅動式I/O模型

66043283-file_1492002950669_22bd.png

首先開啓套接字的信號驅動式IO功能,並且通過 sigaction 系統調用安裝一個信號處理函數,該函數調用將立即返回,當前進程沒有被阻塞,繼續工作;當數據報準備好的時候,內核則爲該進程產生 SIGIO 的信號,隨後既可以在信號處理函數中調用 recvfrom 讀取數據報,並且通知主循環數據已經準備好等待處理,也可以通知主循環讓它讀取數據報;(其實就是一個待讀取的通知和待處理的通知);

2.5 異步式I/O模型

75136497-file_1492004375006_bcbe.png

我們調用 aio_read 函數,給內核傳遞描述符、緩衝區指針、緩衝區大小和文件偏移,並且告訴內核當整個操作完成時如何通知我們。該函數調用後立即返回,不被阻塞;

185128-file_1491989742145_181eb.png

2.6 比較

48821302-file_1492005018721_d9f5.png

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