1. 程式人生 > >*****socket同步非同步阻塞非阻塞區別

*****socket同步非同步阻塞非阻塞區別

首先來解釋同步和非同步的概念,這兩個概念與訊息的通知機制有關.

舉個例子,比如我去銀行辦理業務,可能選擇排隊等候,也可能取一個小紙條上面有我的號碼,等到排到我這一號時由櫃檯的人通知我輪到我去辦理業務了.
前者(排隊等候)就是同步等待訊息,而後者(等待別人通知)就是非同步等待訊息.在非同步訊息處理中,等待訊息者(在這個例子中就是等待辦理業務的人)往往註冊一個回撥機制,在所等待的事件被觸發時由觸發機制(在這裡是櫃檯的人)通過某種機制(在這裡是寫在小紙條上的號碼)找到等待該事件的人.
而在實際的程式中,同步訊息處理就好比簡單的read/write操作,它們需要等待這兩個操作成功才能返回;而非同步處理機制就是類似於select/poll之類的多路複用IO操作,當所關注的訊息被觸發時,由訊息觸發機制通知觸發對訊息的處理.

其次再來解釋一下阻塞和非阻塞,這兩個概念與程式等待訊息(無所謂同步或者非同步)時的狀態
有關.
繼續上面的那個例子,不論是排隊還是使用號碼等待通知,如果在這個等待的過程中,等待者除了等待訊息之外不能做其它的事情,那麼該機制就是阻塞的,表現在程式中,也就是該程式一直阻塞在該函式呼叫處不能繼續往下執行.相反,有的人喜歡在銀行辦理這些業務的時候一邊打打電話發發簡訊一邊等待,這樣的狀態就是非阻塞的,因為他(等待者)沒有阻塞在這個訊息通知上,而是一邊做自己的事情一邊等待.但是需要注意了,第一種同步非阻塞形式實際上是效率低下的,想象一下你一邊打著電話一邊還需要擡頭看到底隊伍排到你了沒有,如果把打電話和觀察排隊的位置看成是程式的兩個操作的話,這個程式需要在這兩種不同的行為之間來回的切換,效率可想而知是低下的;而後者,非同步非阻塞形式卻沒有這樣的問題,因為打電話是你(等待者)的事情,而通知你則是櫃檯(訊息觸發機制)的事情,程式沒有在兩種不同的操作中來回切換.

很多人會把同步和阻塞混淆,我想是因為很多時候同步操作會以阻塞的形式表現出來,比如很多人會寫阻塞的read/write操作,但是別忘了可以對fd設定O_NONBLOCK標誌位,這樣就可以將同步操作變成非阻塞的了;同樣的,很多人也會把非同步和非阻塞混淆,因為非同步操作一般都不會在真正的IO操作處被阻塞,比如如果用select函式,當select返回可讀時再去read一般都不會被阻塞,就好比當你的號碼排到時一般都是在你之前已經沒有人了,所以你再去櫃檯辦理業務就不會被阻塞.

可見,同步/非同步與阻塞/非阻塞是兩組不同的概念,它們可以共存組合,也可以參見這裡:
http://www.ibm.com/developerworks/cn/linux/l-async/