Python中幾個比較容易混淆的概念的解釋

在Python的協程和多線程等相關的編程中,我們經常都會遇到這樣幾個專業名詞——併發、並行、同步、異步、阻塞和非阻塞,很多童鞋都對這幾個詞有一定程度上的誤解和混淆,在本篇我們就來講講這幾個概念究竟有什麼區別。

1. 併發和並行

併發是指一個時間段內,有幾個程序在同一個CPU上運行,但是任意時刻只有一個程序在CPU上運行。通俗講就相當於是一個人交替做不同事情的能力,這裏強調的是一個人來做。那爲什麼他要交替着做不同的事情呢?一般都是遇到有需要等待的事件,比如泡茶的時候,先把水燒上再去洗杯子、放茶葉。燒水是需要等待的(類似於IO這種耗時操作),在等待的時候我去做別的事(洗杯子、放茶葉),這就是併發。

並行是指任意時刻點上,有多個程序同時運行在多個CPU上,所以最大並行數跟CPU的核數相同。這裏強調的是多個人同時做不同的事情。比如在同一時間內,張三看書、李四聽歌、王五玩遊戲,幾個人在做不同的事,這就是並行。

2. 同步和異步

同步和異步關注的是消息通信機制 (synchronous communication/ asynchronous communication)。

同步是指代碼調用IO操作時,必須等待IO操作完成才返回的調用方式。換句話說,就是由*調用者*主動等待這個*調用*的結果。要注意一點,這裏說的IO操作並不僅僅是指狹義上的磁盤讀寫操作,而是泛指一切耗時操作,比如休眠、網絡請求等,都屬於IO操作這個範疇。

異步跟同步正好相反,指代碼調用IO操作時,不必等待IO操作完成就返回的一種調用方式。換句話說,當一個異步過程調用發出後,調用者不會立刻得到結果。而是在*調用*發出後,*被調用者*通過狀態、通知來通知調用者,或通過回調函數處理這個調用。
多線程就是一個典型的異步操作,比如通過線程池submit一個task之後,立即就會得到返回的一個future對象,後期我們就可以通過這個future對象去拿到異步操作的結果。

舉個通俗的例子:
你打電話問書店老闆有沒有《分佈式系統》這本書,如果是同步通信機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而異步通信機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裏老闆通過“回電”這種方式來回調。注意,異步總是跟回調這個行爲綁定在一起。

3. 阻塞和非阻塞

阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態.

阻塞是指調用函數的時候當前線程被掛起。

非阻塞是指調用函數的時候當前線程不會被掛起,而是立即返回。

還是上面的例子,
你打電話問書店老闆有沒有《分佈式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。
在這裏阻塞與非阻塞與是否同步異步無關。跟老闆通過什麼方式回答你結果無關。

總結一下,阻塞非阻塞關心的是調用方(你自己)的行爲,同步異步關心的是被調用方(書店老闆)的行爲,看起來比較相似,其實是從不同的角度去描述這件事。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章