「阻塞」與"非阻塞"與"同步"與「異步"不能簡單的從字面理解,提供一個從分佈式系統角度的回答。
1.同步與異步
同步和異步關注的是消息通訊機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個*調用*時,在沒有獲得結果以前,該*調用*就不返回。可是一旦調用返回,就獲得返回值了。
換句話說,就是由*調用者*主動等待這個*調用*的結果。html
而異步則是相反,*調用*在發出以後,這個調用就直接返回了,因此沒有返回結果。換句話說,當一個異步過程調用發出後,調用者不會馬上獲得結果。而是在*調用*發出後,*被調用者*經過狀態、通知來通知調用者,或經過回調函數處理這個調用。編程
典型的異步編程模型好比Node.js多線程
舉個通俗的例子:
你打電話問書店老闆有沒有《分佈式系統》這本書,若是是同步通訊機制,書店老闆會說,你稍等,」我查一下",而後開始查啊查,等查好了(多是5秒,也多是一天)告訴你結果(返回結果)。
而異步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,而後直接掛電話了(不返回結果)。而後查好了,他會主動打電話給你。在這裏老闆經過「回電」這種方式來回調。異步
2. 阻塞與非阻塞
阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態.async
阻塞調用是指調用結果返回以前,當前線程會被掛起。調用線程只有在獲得結果以後纔會返回。
非阻塞調用指在不能馬上獲得結果以前,該調用不會阻塞當前線程。分佈式
仍是上面的例子,
你打電話問書店老闆有沒有《分佈式系統》這本書,你若是是阻塞式調用,你會一直把本身「掛起」,直到獲得這本書有沒有的結果,若是是非阻塞式調用,你無論老闆有沒有告訴你,你本身先一邊去玩了, 固然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。
在這裏阻塞與非阻塞與是否同步異步無關。跟老闆經過什麼方式回答你結果無關。異步編程
還有一個例子也很生動,單獨列出來:函數
老張愛喝茶,廢話不說,煮開水。
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步阻塞)
老張以爲本身有點傻
2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)
老張仍是以爲本身有點傻,因而變高端了,買了把會響笛的那種水壺。水開以後,能大聲發出嘀~~~~的噪音。
3 老張把響水壺放到火上,立等水開。(異步阻塞)
老張以爲這樣傻等意義不大
4 老張把響水壺放到火上,去客廳看電視,水壺響以前再也不去看它了,響了再去拿壺。(異步非阻塞)
老張以爲本身聰明瞭。post
所謂同步異步,只是對於水壺而言。
普通水壺,同步;響水壺,異步。
雖然都能幹活,但響水壺能夠在本身完工以後,提示老張水開了。這是普通水壺所不能及的。
同步只能讓調用者去輪詢本身(狀況2中),形成老張效率的低下。url
所謂阻塞非阻塞,僅僅對於老張而言。
立等的老張,阻塞;看電視的老張,非阻塞。
狀況1和狀況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是異步的,可對於立等的老張沒有太大的意義。因此通常異步是配合非阻塞使用的,這樣才能發揮異步的效用。
阻塞模式下,一個線程只能處理一項任務,要想提升吞吐量必須經過多線程。
非阻塞模式下,一個線程永遠在執行計算操做,這個線程所使用的 CPU 核心利用率永遠是 100%,I/O 以事件的方式通知。
在阻塞模式下,多線程每每能提升系統吞吐量,由於一個線程阻塞時還有其餘線程在工做,多線程可讓 CPU 資源不被阻塞中的線程浪費。
而在非阻塞模式下,線程不會被 I/O 阻塞,永遠在利用 CPU。多線程帶來的好處是在多核 CPU 的狀況下利用更多的核。
參考連接:
1. 知乎 嚴肅的回答 https://www.zhihu.com/question/19732473/answer/20851256
2. 同步與阻塞,異步與非阻塞的區別