異步和非阻塞
今天看了篇知乎讨論,将異步和非阻塞講的透徹;在這裡整理出來;
同步異步
同步和異步關注的是 消息通信機制
同步,就是在發出一個 調用 時,在沒有得到結果之前,該調用就不傳回。但是一旦調用傳回,就得到傳回值了。
換句話說,就是由調用者主動等待這個調用的結果。
異步則相反,調用在發出之後,這個調用就直接傳回了,是以沒有傳回結果。換句話說,當一個異步過程調用發出後,調用者不會立刻得到結果。而是在調用發出後,被調用者通過狀态、通知來通知調用者,或通過回調函數處理這個調用。
阻塞與非阻塞
阻塞和非阻塞關注的是 程式在等待調用結果(消息,傳回值)時的狀态.
阻塞調用是指調用結果傳回之前,目前線程會被挂起。調用線程隻有在得到結果之後才會傳回。
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞目前線程。當然,這就不知道調用是否完成,一般通過輪詢定期來探查調用是否完成;
IO層面的同步異步
在處理IO的時候,阻塞和非阻塞都是同步;如:IO多路複用(select/poll/epoll);
隻有使用了特殊API,才是異步IO,如:linux的AIO、Windows的IOCP .NET的beginInvoke/EndInvoke;
通俗的例子
買書
你打電話問書店老闆有沒有《分布式系統》這本書,如果是同步通信機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(傳回結果)。
而異步通信機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接挂電話了(不傳回結果)。然後查好了,他會主動打電話給你。在這裡老闆通過“回電”這種方式來回調。
你打電話問書店老闆有沒有《分布式系統》這本書,你如果是阻塞式調用,你會一直把自己“挂起”,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有傳回結果。
在這裡阻塞與非阻塞與是否同步異步無關。跟老闆通過什麼方式回答你結果無關。
喝茶
另一個有趣的例子:
老張愛喝茶,廢話不說,煮開水。
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步阻塞)
老張覺得自己有點傻
2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)
老張還是覺得自己有點傻,于是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嘀~~~~的噪音。
3 老張把響水壺放到火上,立等水開。(異步阻塞)
老張覺得這樣傻等意義不大
4 老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(異步非阻塞)
老張覺得自己聰明了。
所謂同步異步,隻是對于水壺而言。
普通水壺,同步;響水壺,異步。
雖然都能幹活,但響水壺可以在自己完工之後,提示老張水開了。這是普通水壺所不能及的。
同步隻能讓調用者去輪詢自己(情況2中),造成老張效率的低下。
所謂阻塞非阻塞,僅僅對于老張而言。
立等的老張,阻塞;看電視的老張,非阻塞。
情況1和情況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是異步的,可對于立等的老張沒有太大的意義。是以一般異步是配合非阻塞使用的,這樣才能發揮異步的效用。
整理自:http://www.zhihu.com/question/19732473