阻塞與非阻塞,同步與異步

1 老張把水壺放到火上,立等水開。(同步阻塞程序員

老張以爲本身有點傻異步

2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞socket

老張仍是以爲本身有點傻,因而變高端了,買了把會響笛的那種水壺。水開以後,能大聲發出嘀~~~~的噪音。函數

3 老張把響水壺放到火上,立等水開。(異步阻塞spa

老張以爲這樣傻等意義不大線程

4 老張把響水壺放到火上,去客廳看電視,水壺響以前再也不去看它了,響了再去拿壺。(異步非阻塞事件

老張以爲本身聰明瞭。回調函數

 


 

所謂同步異步,只是對於水壺而言。同步

普通水壺,同步;響水壺,異步。it

雖然都能幹活,但響水壺能夠在本身完工以後,提示老張水開了。這是普通水壺所不能及的。

同步只能讓調用者去輪詢本身(狀況2中),形成老張效率的低下。

 

所謂阻塞非阻塞,僅僅對於老張而言。

立等的老張,阻塞;看電視的老張,非阻塞。

狀況1和狀況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是異步的,可對於立等的老張沒有太大的意義。因此通常異步是配合非阻塞使用的,這樣才能發揮異步的效用。

 

程序員寫程序,不少狀況下,老張和水壺都要涉及,即調用者與被調用者。四種組合模式各有所長。

 

當到銀行後,
.能夠去ATM機前排隊等候                                -- (排隊等候)就是同步等待消息
.能夠去大廳拿號,等到排到個人號時,
 櫃檯的人會通知我輪到我去辦理業務.              -- (等待別人通知)就是異步等待消息.

 

A. 阻塞
阻塞調用是指調用結果返回以前,當前線程會被掛起。函數只有在獲得結果以後纔會返回。
有人也許會把阻塞調用和同步調用等同起來,實際上他是不一樣的。
對於同步調用來講,不少時候當前線程仍是激活的,只是從邏輯上當前函數沒有返回而已。

socket接收數據函數recv是一個阻塞調用的例子。
當socket工做在阻塞模式的時候, 若是沒有數據的狀況下調用該函數,則當前線程就會被掛起,直到有數據爲止。

B. 非阻塞
非阻塞和阻塞的概念相對應,指在不能馬上獲得結果以前,該函數不會阻塞當前線程,而會馬上返回。

 

同步阻塞形式:
  效率是最低的,
  拿上面的例子來講,就是你專心排隊,什麼別的事都不作。

  實際程序中
  就是未對fd 設置O_NONBLOCK 標誌位的read/write 操做,

異步阻塞形式:
  若是在銀行等待辦理業務的人採用的是異步的方式去等待消息被觸發,也就是領了一張小紙條,
  假如在這段時間裏他不能離開銀行作其它的事情,那麼很顯然,這我的被阻塞在了這個等待的操做上面;


  異步操做是能夠被阻塞住的,只不過它不是在處理消息時阻塞,而是在等待消息被觸發時被阻塞.
  好比select 函數,
  假如傳入的最後一個timeout 參數爲NULL,那麼若是所關注的事件沒有一個被觸發,
  程序就會一直阻塞在這個select 調用處.

同步非阻塞形式:
  其實是效率低下的,
  想象一下你一邊打着電話一邊還須要擡頭看到底隊伍排到你了沒有,
  若是把打電話和觀察排隊的位置當作是程序的兩個操做的話,
  這個程序須要在這兩種不一樣的行爲之間來回的切換,效率可想而知是低下的;

  不少人會寫阻塞的read/write 操做,
  可是別忘了能夠對fd 設置O_NONBLOCK 標誌位,這樣就能夠將同步操做變成非阻塞的了;

異步非阻塞形式:
  效率更高,
  由於打電話是你(等待者)的事情,而通知你則是櫃檯(消息觸發機制)的事情,
  程序沒有在兩種不一樣的操做中來回切換.

  好比說,這我的忽然發覺本身煙癮犯了,須要出去抽根菸,
  因而他告訴大堂經理說,排到我這個號碼的時候麻煩到外面通知我一下(註冊一個回調函數),
  那麼他就沒有被阻塞在這個等待的操做上面,天然這個就是異步+非阻塞的方式了.

  若是使用異步非阻塞的狀況,
  好比aio_*組的操做,當發起一個aio_read 操做時,函數會立刻返回不會被阻塞,
  當所關注的事件被觸發時會調用以前註冊的回調函數進行處理,

相關文章
相關標籤/搜索