怎樣理解阻塞非阻塞與同步異步的區別?

怎樣理解阻塞非阻塞與同步異步的區別?

【整理自知乎】


“阻塞”與"非阻塞"與"同步"與“異步"不能簡單的從字面理解,提供一個從分佈式系統角度的回答。
1.同步與異步
同步和異步關注的是消息通信機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個*調用*時,在沒有得到結果之前,該*調用*就不返回。但是一旦調用返回,就得到返回值了。
換句話說,就是由《¥調用者主動等待這個*調用*的結果。

 

異步則是相反,*調用*在發出之後,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出後,《¥調用者不會立刻得到結果。而是在*調用*發出後,#被調用者#通過狀態、通知來通知《¥調用者,或通過回調函數處理這個調用。

=======+========

舉個通俗的例子:
你打電話問書店老闆有沒有《分佈式系統》這本書,如果是同步通信機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而異步通信機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裏老闆通過“回電”這種方式來回調。

2. 阻塞與非阻塞
阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態.

阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之後纔會返回


非阻塞調用在不能立刻得到結果之前,該調用不會阻塞當前線程

還是上面的例子,
你打電話問書店老闆有沒有《分佈式系統》這本書,

你如果是阻塞式調用,你會一直把自己“掛起”原地閒滯等待),直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。
在這裏阻塞與非阻塞與是否同步異步無關。跟老闆通過什麼方式回答你結果無關。

========+=========

在處理 IO 的時候,阻塞和非阻塞都是同步 IO。
只有使用了特殊的 API 纔是異步 IO。
wKiom1cDjbWzLVJEAAA-HV5oIMg159.png

 

 

 

對unix來講:阻塞式I/O(默認),非阻塞式I/O(nonblock),I/O複用(select/poll/epoll)都屬於同步I/O,因爲它們在數據由內核空間複製回進程緩衝區時都是阻塞的(不能幹別的事)。

只有異步I/O模型(AIO)是符合異步I/O操作的含義的,即在1數據準備完成、2由內核空間拷貝回緩衝區後 通知進程,在等待通知的這段時間裏可以幹別的事。

-********----

一講到網絡編程的I/O模型,總會涉及到這幾個概念。問了很多人,沒幾個能清晰地講出他們之間的區別聯繫,甚至在網絡上也有很多不同的觀點,也不知是中國文字釋義的博大精深,還是本來這幾個概念就是繞人不倦。今天我也來給大家講解一下我對這幾個概念的理解。

既然網絡上衆說紛紜,不如找個權威參考一下,這個權威就是《UNIX網絡編程:卷一》第六章——I/O複用。書中向我們提及了5種類UNIX下可用的I/O模型

· 

阻塞式I/O;

非阻塞式I/O;

I/O複用(select,poll,epoll...);

信號驅動式I/O(SIGIO);

異步I/O(POSIX的aio_系列函數);

· 

阻塞式I/O模型:默認情況下,所有套接字都是阻塞的。怎麼理解?先理解這麼個流程,一個輸入操作通常包括兩個不同階段:

(1)等待數據準備好;
(2)從內核向進程複製數據。

對於一個套接字上的輸入操作,第一步通常涉及等待數據從網絡中到達。當所有等待分組到達時,它被複制到內核中的某個緩衝區。第二步就是把數據從內核緩衝區複製到應用程序緩衝區。 好,下面我們以阻塞套接字的recvfrom的的調用圖來說明阻塞

wKiom1cDjeyCmSrJAADBB4fFTHQ857.png

標紅的這部分過程就是阻塞,直到阻塞結束recvfrom才能返回。

非阻塞式I/O: 以下這句話很重要:進程把一個套接字設置成非阻塞是在通知內核,當所請求的I/O操作非得把本進程投入睡眠才能完成時,不要把進程投入睡眠,而是返回一個錯誤。看看非阻塞的套接字的recvfrom操作如何進行

wKiom1cDjgCD8FsxAAG0STEgHmw383.png

可以看出recvfrom總是立即返回。

I/O多路複用:雖然I/O多路複用的函數也是阻塞的,但是其與以上兩種還是有不同的,I/O多路複用是阻塞在select,epoll這樣的系統調用之上,而沒有阻塞在真正的I/O系統調用如recvfrom之上。如圖

wKioL1cDjr6guQ-_AAEaCZPP3GA168.png

信號驅動式I/O:用的很少,就不做講解了。直接上圖

wKioL1cDjtHifrq_AAD9J9hIr0c333.png

異步I/O:這類函數的工作機制是告知內核啓動某個操作,並讓內核在整個操作(包括將數據從內核拷貝到用戶空間)完成後通知我們。如圖:

wKiom1cDjk***HJ0AADaul7dNP4225.png

注意紅線標記處說明在調用時就可以立馬返回,等函數操作完成會通知我們。

等等,大家一定要問了,同步這個概念你怎麼沒涉及啊?別急,您先看總結。 其實前四種I/O模型都是同步I/O操作,他們的區別在於第一階段,而他們的第二階段是一樣的:在數據從內核複製到應用緩衝區期間(用戶空間),進程阻塞於recvfrom調用。相反,異步I/O模型在這兩個階段都要處理。

wKiom1cDjnKj37nLAAKgBDuvrvE098.png

再看POSIX對這兩個術語的定義:

   同步I/O操作:導致請求進程阻塞,直到I/O操作完成;

   異步I/O操作:不導致請求進程阻塞。

好,下面我用我的語言來總結一下阻塞,非阻塞,同步,異步

   阻塞,非阻塞:進程/線程要訪問的數據是否就緒,進程/線程是否需要等待;

   同步,異步:訪問數據的方式,同步需要主動讀寫數據,在讀寫數據的過程中還是會阻塞;異步只需要I/O操作完成的通知,並不主動讀寫數據,由操作系統內核完成數據的讀寫。

 

 

老張愛喝茶,廢話不說,煮開水。
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步阻塞)
老張覺得自己有點傻
2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)
老張還是覺得自己有點傻,於是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嘀~~~~的噪音。
3 老張把響水壺放到火上,立等水開。(異步阻塞)
老張覺得這樣傻等意義不大
4 老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(異步非阻塞)
老張覺得自己聰明瞭。


所謂同步異步,只是對於水壺而言方式】

普通水壺,同步;響水壺,異步。
雖然都能幹活,但響水壺可以在自己完工之後,提示老張水開了。這是普通水壺所不能及的。
同步只能讓調用者去輪詢自己(情況2中),造成老張效率的低下。



所謂阻塞非阻塞,僅僅對於老張而言狀態

立等的老張,阻塞;看電視的老張,非阻塞。
情況1和情況3中老張就是阻塞的,媳婦喊他都不知道。
雖然3中響水壺是異步的,可對於立等的老張沒有太大的意義。所以一般異步是配合非阻塞使用的,這樣才能發揮異步的效用。

 

 


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