Author:
bugall
Wechat:bugallF
Email:769088641@qq.com
Github: https://github.com/bugallgit
在面試中咱們會碰到這種場景:
面試官:能解釋下什麼是同步,異步麼?程序員
程序員:假如咱們執行A,B兩個IO操做的時候,若是必須等待A完成後才能執行B那麼這個就是github
同步的,若是A,B能夠同時執行那麼就是異步的。面試
面試官:那能解釋下什麼是阻塞什麼是非阻塞麼?編程
程序員:若是必須等待A完成後才能執行B那麼這個就是阻塞的,若是A,B能夠同時執行那麼就 是非阻塞的多線程
面試官:那你的意思異步/同步的概念與阻塞非阻塞同樣了?併發
程序員:嗄。。。能夠這麼說吧。我以爲能夠併發執行
的就是異步非阻塞的。one by one執行 的就是同步阻塞的異步
每一個人看去看同一個問題都會有不一樣的理解,緣由就是由於每一個人的看待問題的深度不同,就像上面的對白,程
序員的理解只是停留在應用層面,代碼裏有多個IO操做,每一個IO操做均可以不用互相等待的「同時」執行。函數
接下來咱們就來探討下異步/同步與阻塞/非阻塞它們其中的區別。操作系統
阻塞 / 非阻塞描述的是函數, 指訪問某個函數時是否會阻塞線程(block),致使線程進入阻塞狀態。
同步 / 異步描述的是執行IO操做的主體是誰,同步是由用戶態的進程本身去執行IO操做,異步是用戶態進程不關心IO細節,由內核態進程去完成IO操做而後通知用戶態進程。
好的,如今定義已經描述完了。如今能夠區分它們之間的區別了麼?(吃瓜羣衆:這TM的寫的是什麼?) ,別急,咱們下面舉慄說明,包教包會。
通常來講IO分爲兩個階段,第一階段是等待數據階段,第二階段是內核空間的數據拷貝到用戶空間,假設一個線程(或是進程)P準備執行一個IO操做的話它會經歷如下過程:
第一階段:
P發出一個IO請求,這時候會有兩種狀況: 1:馬上返回: 非阻塞 2:一直等待,P調用sleep/wait休眠或是掛起,讓出CPU給別的線程/進程 阻塞
第二階段:
這時內核的數據終於準備好了, 那麼如今用戶進程想要讀取內核空間的數據有兩種方式: 1: P本身把數據從內核空間拷貝到用戶空間 同步 2:P建立一個線程作數據copy的工做 異步
如今應該明白了吧。阻塞/非阻塞是針對IO的第一階段的描述。異步/同步是針對IO的第二階段的描述也就是IO的主體。
這裏主要比較難理解的就是同步/異步。首先P在發起IO的請求的時候若是P自己還要負責IO請求後的數據copy(內核空間到用戶空間)工做。那麼咱們就能夠說是同步的。
若是P在發起IO操做後數據copy的工做由內核線程/進程或是P本身再建立一個線程/進程去完成,那麼咱們就能夠稱之爲異步
同步阻塞IO:
同一個線程在操做IO時一直阻塞,直到讀取數據成功,而後線程自己負責把數據從核心空間拷貝到用戶空間
同步非阻塞:
同一個線程發起IO後,當即得到返回,後面按期輪詢數據讀取狀況,發現數據讀取成功,線程自己負責把數據從核心空間拷貝到用戶空間
異步非阻塞:
一個線程發起IO後,當即返回,由另外的線程發現數據讀取成功,把數據從核心空間拷貝到用戶空間。
非阻塞同步IO因爲讀寫方法非阻塞,而且須要用戶本身來進行讀寫,因此每次調用讀寫方法實際讀寫的字節數是不肯定的,因此須要一個Buffer來保存每次讀寫的字節狀態。更重要的是用戶不知道何時完成了讀寫,通常須要用
while循環判斷Buffer的狀態來跟蹤讀寫。非阻塞異步IO因爲是內核線程進行讀寫,而且在IO完成後會回調用戶提供的callback,編程模型就比較簡單,用戶只須要調用讀寫,提供回調就能夠了,好比 read(filename, callback)select / poll / epoll 從本質上說都是非阻塞同步IO,select會收到IO就緒的狀態,而後通知用戶去處理
IO,實際的IO操做還須要用戶等待內核複製操做。
要理解IO就緒和完成的區別。就緒指的是還須要用戶本身去處理,完成指的是內核幫助完成了,用戶不用關心IO過
程,只須要提供回調函數。
對多處理器而言--多個程序在同一時刻發生,具備併發的含義,但併發不必定並行,也亦是說併發事件之間不必定要同一時刻發生。
並行:在單處理器中多道程序設計系統中,進程被交替執行,表現出一種併發的外部特種;在多處理器系統中,進
程不只能夠交替執行,並且能夠重疊執行。在多處理器上的程序纔可實現並行處理。計算機操做系統中把並行性和併發性明顯區分開,主要是從微觀的角度來講的,具體是指進程的並行性(多處理機的狀況下,多個進程同時運行)和併發性(單處理機的狀況下,多個進程在同一時間間隔運行的)
對單處理器而言--多個程序在同一時間段發生;
併發中又有:互斥和同步:
互斥:進程間相互排斥使用臨界資源;好比寫操做; 同步:不是排斥關係而是依賴關係,前一個進程的輸出是後一個進程的輸入 當第一個進程沒有結束時第二個進程必須等待,相互協同完成一些事情; 具備同步關係的一組進程併發時發送的消息稱爲消息或者事件;
同步和異步:
異步:就是線程B在等待A的結果的時候還能夠繼續幹本身的事兒, 之間經過消息和事件來通知對方,提升了程序運行的效率。 簡而言之,就是否是站在那兒傻傻死等;異步和多線程並非一回事, 異步是最終目的,多線程只是實現的一種方法。