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

 本篇文章來源於 Linux公社網站(www.linuxidc.com)  原文連接:http://www.linuxidc.com/Linux/2015-07/120338.htmlinux

 

「阻塞」與"非阻塞"與"同步"與「異步"不能簡單的從字面理解,提供一個從分佈式系統角度的回答。編程

1.同步與異步
同步和異步關注的是消息通訊機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個*調用*時,在沒有獲得結果以前,該*調用*就不返回。可是一旦調用返回,就獲得返回值了。
換句話說,就是由*調用者*主動等待這個*調用*的結果。異步

而異步則是相反,*調用*在發出以後,這個調用就直接返回了,因此沒有返回結果。換句話說,當一個異步過程調用發出後,調用者不會馬上獲得結果。而是在*調用*發出後,*被調用者*經過狀態、通知來通知調用者,或經過回調函數處理這個調用。socket

典型的異步編程模型好比Node.jsasync

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

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

阻塞調用是指調用結果返回以前,當前線程會被掛起。調用線程只有在獲得結果以後纔會返回。
非阻塞調用指在不能馬上獲得結果以前,該調用不會阻塞當前線程。異步編程

仍是上面的例子,
你打電話問書店老闆有沒有《分佈式系統》這本書,你若是是阻塞式調用,你會一直把本身「掛起」,直到獲得這本書有沒有的結果,若是是非阻塞式調用,你無論老闆有沒有告訴你,你本身先一邊去玩了, 固然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。
在這裏阻塞與非阻塞與是否同步異步無關。跟老闆經過什麼方式回答你結果無關。函數

在處理 IO 的時候,阻塞和非阻塞都是同步 IO。
只有使用了特殊的 API 纔是異步 IO。網站


對unix來說:阻塞式I/O(默認),非阻塞式I/O(nonblock),I/O複用(select/poll/epoll)都屬於同步I/O,由於它們在數據由內核空間複製回進程緩衝區時都是阻塞的(不能幹別的事)。只有異步I/O模型(AIO)是符合異步I/O操做的含義的,即在1數據準備完成、2由內核空間拷貝回緩衝區後 通知進程,在等待通知的。

以Linux下 tcp socket編程爲例:

阻塞就是 recv/read的時候 socket接收緩衝區要是有數據就讀, 沒數據我就一直睡覺賴着不走,直到有數據來了讀完我才走。send/write的時候,要是發送緩衝區滿了,沒有空間繼續發送了我也一直睡覺賴着不走,直到發送緩衝區騰出足夠的空間讓我把數據所有塞到發送緩衝區裏我才走。(固然若是你經過setsockopt設置了讀寫超時,超時時間到了仍是會返回-1和EAGAIN,再也不睡覺等待)

各一句話
IO時進入內核代碼沒有當即返回,則直到返回前用戶的進程代碼一直處於「阻塞」狀態。
從IO請求到數據複製到進程空間的過程當中,若進程代碼發生過阻塞,則IO過程是「同步」的,反之「異步」。

同步和異步僅僅是關於所關注的消息如何通知的機制。同步的狀況下,是由處理消息者本身去等待消息是否被觸發,而異步的狀況下是由觸發機制來通知處理消息者
阻塞和非阻塞應該是發生在消息的處理的時刻。阻塞其實就是等待,發出通知,等待結果完成。非阻塞屬於發出通知,當即返回結果,沒有等待過程。

關於同步異步、阻塞非阻塞的概念: 同步就是同步,異步就是異步! 目前應用中阻塞和非阻塞是針對同步應用而言。關於這些概念之間的關係的理解,能夠經過如下幾個例子來講明。

例子1:老闆佈置了一個調研任務,老闆本身須要寫一個調研報告。這個調研的一個子任務由同窗A完成,老闆最終須要將同窗A的任務整合到本身的調研報告中。由於老闆的調研報告須要用到同窗A的調研結果,那麼老闆的調研報告就必須等到同窗A調研完成之後才能完成。那麼在整個調研的過程當中,最終的調研報告和同窗A的調研任務之間就是同步關係,由於兩個任務之間有着時序的關係。

首先一個IO操做其實分紅了兩個步驟:發起IO請求和實際的IO操做,同步IO和異步IO的區別就在於第二個步驟是否阻塞,若是實際的IO讀寫阻塞請求進程,那麼就是同步IO,所以阻塞IO、非阻塞IO、IO服用、信號驅動IO都是同步IO,若是不阻塞,而是操做系統幫你作完IO操做再將結果返回給你,那麼就是異步IO。阻塞IO和非阻塞IO的區別在於第一步,發起IO請求是否會被阻塞,若是阻塞直到完成那麼就是傳統的阻塞IO,若是不阻塞,那麼就是非阻塞IO。

看了一些這兩個概念的解釋,感受不分場景的籠統理解是不對的,下面陳述一下個人理解:

這是兩對概念,用在不一樣的語境會有一些不一樣的含義,不能一律而論。

總體來講,同步就是兩種東西經過一種機制實現步調一致,異步是兩種東西沒必要步調一致。

1、同步調用與異步調用:

在用在調用場景中,無非是對調用結果的不一樣處理。

我理解同步調用就是調用一但返回,就能知道結果,而異步是返回時不必定知道結果,還得經過其餘機制來獲知結果,如:

a. 狀態

b. 通知

c. 回調函數

這裏的同步調用不必定會阻塞,例如當即返回失敗的結果。

而異步調用當即返回時,你還拿不到結果的。

2、同步線程與異步線程:

同步線程:即兩個線程步調要一致,要相互協商。兩個線程的運行進度各不相同,怎麼才能步調一致呢?咱們直觀的理解就是,快的等慢的唄!快的阻塞一下等到慢的步調一致便可。

異步線程:步調不用一致,各自按各自的步調運行,不受另外一個線程的影響。

同步是指兩個線程的運行是相關的,其中一個線程可能要阻塞等待另一個線程的運行;

異步的意思是兩個線程毫無相關,本身運行本身的。

3、同步通訊與異步通訊:

這裏的同步和異步是指:發送方和接收方是否協調步調一致!

同步通訊是指:發送方和接收方經過必定機制,實現收發步調協調。如:發送方發出數據後,等接收方發回響應之後才發下一個數據包的通信方式

異步通訊是指:發送方的發送無論接收方的接收狀態,如:發送方發出數據後,不等接收方發回響應,接着發送下個數據包的通信方式。

阻塞和非阻塞就比較容易理解了,沒有上面那麼多場景,阻塞就是這個事情阻到這兒了,不能繼續往下幹事了,非阻塞就是這個事情不會阻礙你繼續幹後面的事情。

阻塞能夠是實現同步的一種手段!例如兩個東西須要同步,一旦出現不一樣步狀況,我就阻塞快的一方,使雙方達到同步。

同步是兩個對象之間的關係,而阻塞是一個對象的狀態。

本篇文章來源於 Linux公社網站(www.linuxidc.com) 原文連接:http://www.linuxidc.com/Linux/2015-07/120338.htm

相關文章
相關標籤/搜索