1. 程式人生 > >明明白白學 同步、非同步、阻塞與非阻塞

明明白白學 同步、非同步、阻塞與非阻塞

1、同步與非同步

概率理解

同步與非同步主要是從訊息通知機制角度來說的

  • 同步就是一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成後,依賴的任務才能算完成,這是一種可靠的任務序列。
  • 非同步是不需要等待被依賴的任務完成,只是通知被依賴的任務要完成什麼工作,依賴的任務也立即執行,只要自己完成了整個任務就算完成了。至於被依賴的任務最終是否真正完成,依賴它的任務無法確定,所以它是不可靠的任務序列。

場景比喻

舉個例子:去銀行辦理業務,可能會有兩種方式

1、選擇排隊等候;

2、選擇取一個小紙條上面有我的號碼,等到排到我這一號時由櫃檯的人通知我輪到我去辦理業務了;

第一種:前者(排隊等候)就是同步等待訊息通知,也就是我要一直在等待銀行辦理業務情況;

第二種:後者(等待別人通知)就是非同步等待訊息通知。在非同步訊息處理中,等待訊息通知者(在這個例子中就是等待辦理業務的人)往往註冊一個回撥機制,在所等待的事件被觸發時由觸發機制(在這裡是櫃檯的人)通過某種機制(在這裡是寫在小紙條上的號碼,喊號)找到等待該事件的人。

2、阻塞與非阻塞

概念理解

阻塞與非阻塞主要是程式(執行緒)等待訊息通知時的狀態角度來說的

  • 阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起,一直處於等待訊息通知,不能夠執行其他業務。函式只有在得到結果之後才會返回。
  • 非阻塞呼叫指在不能立刻得到結果之前,該函式不會阻塞當前執行緒,而會立刻返回

場景比喻

繼續上面的那個例子,不論是排隊還是使用號碼等待通知,如果在這個等待的過程中,等待者除了等待訊息通知之外不能做其它的事情,那麼該機制就是阻塞的,表現在程式中,也就是該程式一直阻塞在該函式呼叫處不能繼續往下執行。

相反,有的人喜歡在銀行辦理這些業務的時候一邊打打電話發發簡訊一邊等待,這樣的狀態就是非阻塞的,因為他(等待者)沒有阻塞在這個訊息通知上,而是一邊做自己的事情一邊等待。

但是需要注意了,同步非阻塞形式實際上是效率低下的,想象一下你一邊打著電話一邊還需要抬頭看到底隊伍排到你了沒有。如果把打電話和觀察排隊的位置看成是程式的兩個操作的話,這個程式需要在這兩種不同的行為之間來回的切換,效率可想而知是低下的;而非同步非阻塞形式卻沒有這樣的問題,因為打電話是你(等待者)的事情,而通知你則是櫃檯(訊息觸發機制)的事情,程式沒有在兩種不同的操作中來回切換。

3、同步阻塞形式

​ 效率是最低的,拿上面的例子來說,就是你專心排隊,什麼別的事都不做。

4、非同步阻塞形式

​ 如果在銀行等待辦理業務的人採用的是非同步的方式去等待訊息被觸發(通知),也就是領了一張小紙條,假如在這段時間裡他不能離開銀行做其它的事情,那麼很顯然,這個人被阻塞在了這個等待的操作上面;

非同步操作是可以被阻塞住的,只不過它不是在處理訊息時阻塞,而是在等待訊息通知時被阻塞。

比如select 函式,假如傳入的最後一個timeout引數為NULL,那麼如果所關注的事件沒有一個被觸發,程式就會一直阻塞在這個select 呼叫處

5、同步非阻塞形式

​ 實際上是效率低下的,想象一下你一邊打著電話一邊還需要抬頭看到底隊伍排到你了沒有,如果把打電話和觀察排隊的位置看成是程式的兩個操作的話,這個程式需要在這兩種不同的行為之間來回的切換,效率可想而知是低下的。

6、非同步非阻塞形式

​ 效率更高,因為打電話是你(等待者)的事情,而通知你則是櫃檯(訊息觸發機制)的事情,程式沒有在兩種不同的操作中來回切換。

比如說,這個人突然發覺自己煙癮犯了,需要出去抽根菸,於是他告訴大堂經理說,排到我這個號碼的時候麻煩到外面通知我一下(註冊一個回撥函式),那麼他就沒有被阻塞在這個等待的操作上面,自然這個就是非同步+非阻塞的方式了。

7、小明的故事

對上面所講的概念再次進行一個場景梳理,上面已經明確說明,同步/非同步關注的是訊息通知的機制,而阻塞/非阻塞關注的是程式(執行緒)等待訊息通知時的狀態。以小明下載檔案打個比方,從這兩個關注點來再次說明這兩組概念,希望能夠更好的促進大家的理解。

  1. 同步阻塞:小明一直盯著下載進度條,到 100% 的時候就完成。

同步體現在:等待下載完成通知;

阻塞體現在:等待下載完成通知過程中,不能做其他任務處理;

  1. 同步非阻塞:小明提交下載任務後就去幹別的,每過一段時間就去瞄一眼進度條,看到 100% 就完成。

同步體現在:等待下載完成通知;

非阻塞體現在:等待下載完成通知過程中,去幹別的任務了,只是時不時會瞄一眼進度條;【小明必須要在兩個任務間切換,關注下載進度】

  1. 非同步阻塞:小明換了個有下載完成通知功能的軟體,下載完成就“叮”一聲。不過小明仍然一直等待“叮”的聲音(看起來很傻,不是嗎)。

非同步體現在:下載完成“叮”一聲通知;

阻塞體現在:等待下載完成“叮”一聲通知過程中,不能做其他任務處理;

  1. 非同步非阻塞:仍然是那個會“叮”一聲的下載軟體,小明提交下載任務後就去幹別的,聽到“叮”的一聲就知道完成了。

非同步體現在:下載完成“叮”一聲通知;

非阻塞體現在:等待下載完成“叮”一聲通知過程中,去幹別的任務了,只需要接收“叮”聲通知即可;【軟體處理下載任務,小明處理其他任務,不需關注進度,只需接收軟體“叮”聲通知,即可】

也就是說,同步/非同步是“下載完成訊息”通知的方式(機制),而阻塞/非阻塞則是在等待“下載完成訊息”通知過程中的狀態(能不能幹其他任務),在不同的場景下,同步/非同步、阻塞/非阻塞的四種組合都有應用。

所以,綜上所述,同步和非同步僅僅是關注的訊息如何通知的機制,而阻塞與非阻塞關注的是等待訊息通知時的狀態。也就是說,同步的情況下,是由處理訊息者自己去等待訊息是否被觸發,而非同步的情況下是由觸發機制來通知處理訊息者,所以在非同步機制中,處理訊息者和觸發機制之間就需要一個連線的橋樑

在銀行的例子中,這個橋樑就是小紙條上面的號碼。

在小明的例子中,這個橋樑就是軟體“叮”的聲音。

參考連結:

聊聊同步、非同步、阻塞與非阻