聊聊同步異步、阻塞非阻塞

背景

很多人在同步異步、阻塞非阻塞這2組概念上不能講的很清楚,而且網絡上也有幾種完全不同的看法,總之這個部分有不少爭議。

筆者也在這部分困惑過,花了一些時間去弄透這個問題,以下是個人理解的一些總結。希望能幫到大家。

1. 通用概念

例子:”我”燒水(注意:這裏的主語是”我”,也就是我們討論的who)

1.1. 同步異步

1.1.1. 例子

關注點:是否需要”我主動”去看水燒開沒(注意,”我”和”主動”這兩個詞)

  • 同步:“我”要主動看水燒開沒
  • 異步:不需要”我”主動去看水燒開,水壺響了通知”我”

1.1.2. 概念

抽象概念:事情執行者對事情結果的獲取機制(who:事情執行者)

  • 同步:事情執行者主動獲取事情結果
  • 異步:事情執行者被動獲取事情結果

1.2. 阻塞非阻塞

1.2.1. 例子

關注點:水燒開前,”我”能不能去做其他事情

  • 阻塞: 
    1. 水沒燒開,我一直等着(全程阻塞)
    2. 我去幹其他事情了,但是隔一會兒來看一次水燒開沒(來看的時候阻塞)
  • 非阻塞: 
    水沒燒開,”我”去拖地了,拖完地又看了會兒電視

1.2.2. 概念

抽象概念:事情執行者得到事情結果前能不能去做其他事情(who:事情執行者

  • 阻塞:事情執行者得到結果前不能去做其他事情
  • 非阻塞:事情執行者得到結果前可以去做其他事情

1.3. 總結

  1. 同步一定是會發生阻塞的,只是阻塞的時間長短問題。 
    • 我主動看水燒開(同步),水燒開前我一直等着(阻塞):全程阻塞
    • 我主動看水燒開(同步),隔一會兒來看水燒開(看的過程是阻塞):局部阻塞
  2. 異步一定是非阻塞的: 
    • 不需要我主動去看水燒開(異步),燒水過程中我可以去做任何事情(非阻塞)。

2. 網絡編程層面

網絡編程層面主要涉及的就是IO,所以,這裏主要講IO。這塊兒其實在《UNIX網絡編程卷1 第6章 IO複用》中講的非常清楚了,建議大家看一下,我引用其中的一些關鍵點。具體的可以找書去看。

2.1. POSIX定義

  • 同步I/O操作:導致請求進程阻塞,直到I/O操作完成;
  • 異步I/O操作:不導致請求進程阻塞。

2.2. IO模型

根據POXIX的定義,下面圖中的五種IO模型,其實前四種都是同步IO。 
 

2.3. 總結

注意:這裏的who是進程

2.3.1. 同步IO

  1. 進程主動查看關心的IO事件是否就緒,就緒時再執行相關操作 
    • 注意:進程的阻塞發生在select/epoll/poll等待事件時
  2. 進程主動執行讀寫 
    • 注意:進程的阻塞發生在數據未到達(設備未收到數據),或者未就緒(內核空間和用戶空間的數據copy未完成)

2.3.2. 異步IO

異步IO是需要底層操作系統內核做支持的,比如linux的AIO, windows的IOCP。

  1. 進程不用主動去查看關心的IO事件,只需要把關心的IO事件、數據buffer以及要綁定的回調函數或者signal直接告訴內核,內核發現IO時間就緒時,直接調用回調函數或者發送綁定的signal 
    • 注意:IO事件相關的數據,由內核直接將數據copy到用戶空間(異步讀),或者從用戶空間copy至內核空間(異步寫)
  2. 進程被動執行數據操作 
    • 注意:進程收到內核通知後,在1中綁定的數據buffer裏就已經有數據了,進程直接對數據進行相關處理即可。
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章