1. 程式人生 > >組塞式,非阻塞式,同步非同步

組塞式,非阻塞式,同步非同步

請求描述: `阻塞/非阻塞` 和 `同步/非同步` 不是一個概念。舉幾個簡單的例子。          當程序呼叫一個進行IO操作的API時(比如read函式),在資料沒有到達前,read 會掛起,程序會卡住。在資料讀取完畢返回給程序時,       read 返回(返回值為讀取到的位元組數,資料從核心拷貝到使用者空間),然後程序繼續執行。那麼這次 read 呼叫,是阻塞的。          非阻塞就是 read 在資料沒有讀取完畢前,就返回了(返回值為-1,errno 設定為 EAGAIN)。此時程序沒有拿到需要的資料。那怎麼辦?

有兩種辦法。

一種是同步:        因為程序沒辦法知道資料什麼時候才真正讀取完畢了,所以需要每隔一段時間就去輪詢一下(就是重新呼叫 read,看是不是資料真的已經讀取完畢了)。    大部分場景中都不會使用這種方式。但在某些特殊的情況下效率會特別高。一種是非同步:      早期的非同步實現方式是核心給程序發訊號(SIGIO 或者 SIGPOLL)。資料讀寫完畢後,核心發訊號給程序,然後程序內的訊號處理函式再呼叫 read 讀取資料(這時可以確保資料真的已經讀取完畢了)。但這種方式有一個小小的瑕疵,就是在程序進行多個 fd 讀寫的時候,訊號來的時候沒辦法分清到底是哪個 fd 上的資料已經真正準備好了。所以程序還是要對所有持有的 fd 進行 read 呼叫。     後來的非同步實現,就有了更好的 select / poll / epoll(I/O multiplexing)。現在基本上像比較流行的 Nginx / Redis 都用 epoll(在 FreeBSD 上是 kqueue) --------------------- 作者:樂楊俊 來源:CSDN 原文:https://blog.csdn.net/leyangjun/article/details/62236241 版權宣告:本文為博主原創文章,轉載請附上博文連結!

 

    小樂愛喝茶,廢話不說,煮開水。    

出場人物:小樂,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。       

1 小樂把水壺放到火上,立等水開。(同步阻塞)      

    ——   小樂覺得自己有點傻     

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

     ——  小樂還是覺得自己有點傻,於是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嗚嗚~~~~的噪音。      

  3 小樂把響水壺放到火上,立等水開。(非同步阻塞)        

     ——  小樂覺得這樣傻等意義不大       

4 小樂把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(非同步非阻塞)         

——  小樂覺得自己聰明瞭。  

所謂同步非同步,只是對於水壺而言。      普通水壺,同步;響水壺,非同步。      雖然都能幹活,但響水壺可以在自己完工之後,提示小樂水開了。這是普通水壺所不能及的。     

同步只能讓呼叫者去輪詢自己(情況2中),造成小樂效率的低下。   

所謂阻塞非阻塞,僅僅對於小樂而言。    

—— 立等的小樂,阻塞;看電視的小樂,非阻塞。    

情況1和情況3中小樂就是阻塞的,媳婦喊他都不知道。    

雖然3中響水壺是非同步的,可對於立等的小樂沒有太大的意義。   

  所以一般非同步是配合非阻塞使用的,這樣才能發揮非同步的效用。