python進階04IO的同步異步,阻塞非阻塞

原創博客地址:python進階04IO的同步異步,阻塞非阻塞

同步和異步

同步和異步關注的是消息通信機制
所謂同步,就是在發出一個調用時,在沒有得到結果之前,該調用就不返回。但是一旦調用返回,就得到返回值了。
換句話說,就是由調用者主動等待這個調用的結果。
而異步則是相反,調用在發出之後,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出後,調用者不會立刻得到結果。而是在調用發出後,被調用者通過狀態、通知來通知調用者,或通過回調函數處理這個調用。
舉個通俗的例子:你打電話問書店老闆有沒有《分佈式系統》這本書,如果是同步通信機制,書店老闆會說,你稍等,”我查一下”,然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。而異步通信機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裏老闆通過“回電”這種方式來回調。
同步的整個流程就1部分,1問答,異步模式2部分,1問空答覆+無問1答覆。

阻塞和非阻塞

阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態.
阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之後纔會返回。
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。
你打電話問書店老闆有沒有《分佈式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。在這裏阻塞與非阻塞與是否同步異步無關。跟老闆通過什麼方式回答你結果無關。

還是上面的例子,你打電話問書店老闆有沒有《分佈式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。在這裏阻塞與非阻塞與是否同步異步無關。跟老闆通過什麼方式回答你結果無關。如果是關心阻塞 IO/ 異步 IO, 參考 Unix Network Programming View Book–還是2014年寫的以解釋概念爲主,主要是同步異步 阻塞和非阻塞會被用在不同層面上,可能會有不準確的地方,並沒有針對 阻塞 IO/ 異步 IO 等進行討論,大家可以後續看看這兩個回答:

作者:Yi Lu
鏈接:https://www.zhihu.com/question/19732473/answer/20851256

例子:老張水壺

老張愛喝茶,廢話不說,煮開水。
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步阻塞)
2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)
老張還是覺得自己有點傻,於是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嘀~的噪音。
3 老張把響水壺放到火上,立等水開。(異步阻塞)
4 老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(異步非阻塞)
所謂同步異步,只是對於水壺而言。
普通水壺,同步;響水壺,異步。雖然都能幹活,但響水壺可以在自己完工之後,提示老張水開了。這是普通水壺所不能及的。同步只能讓調用者去輪詢自己(情況2中),造成老張效率的低下。
所謂阻塞非阻塞,僅僅對於老張而言。
立等的老張,阻塞;看電視的老張,非阻塞。情況1和情況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是異步的,可對於立等的老張沒有太大的意義。所以一般異步是配合非阻塞使用的,這樣才能發揮異步的效用。

作者:愚抄
鏈接:https://www.zhihu.com/question/19732473/answer/23434554

同步異步,阻塞非阻塞

二者其實是不同維度的東西,但是的確容易搞混,

客服 做法 說明
    做法A(同步,阻塞) 啥也不做,假裝沒聽到他問話,電話不掛機,就呆呆放那
打電話:請問特朗普給我留言了麼? 掃了一眼小本本,發現沒留言 做法B(同步,非阻塞) 告訴你,啥也沒有(None),然後掛掉電話
通話期間(手持話筒)你不能一心二用   做法C(異步,非阻塞) 告訴你,請留下電話,回頭收到消息第一時間通知你
    做法D(異步,阻塞) 沒想到現實場景,理論上應該不存在,除非代碼bug

代碼特徵:
做法A(同步,阻塞) :開單獨線程(進程)處理,線程內一般是循環接收消息。
做法B(同步,非阻塞) :主線程循環處理,但一般搭配sleep函數(釋放時間片,自身狀態運行轉就緒再等待時間片),避免完全的cpu空轉
做法C(異步,非阻塞):函數參數包含函數(回調函數),或url地址,類似的東西,對方有消息就推送給你,所以還需要新開一個接口(or功能)用來接受信息。
至於A,B實例可參考本博客的 “django進階系列02websocket” ,C實例就不多說了,js中非常常見。

參考

怎樣理解阻塞非阻塞與同步異步的區別
NIO詳解(二): BIO 淺談 同步 異步與阻塞 非阻塞
怎樣理解同步異步和阻塞非阻塞

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