1. 程式人生 > >python中的同步和非同步、阻塞和非阻塞

python中的同步和非同步、阻塞和非阻塞

同步與非同步

同步和非同步關注的是訊息通訊機制.
同步非同步指的是呼叫者與被呼叫者兩者之間的關係,而不是經常容易誤解的多個被呼叫者之間的關係。

同步

所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不會返回,一旦呼叫返回,就得到返回值了。
換句話說,就是由呼叫者主動等待這個呼叫結果.按照此定義,其實絕大多數函式都是同步呼叫。但是一般而言,我們在說同步、非同步的時候,特指那些需要其他程式或者IO協作或者需要一定時間完成的任務。

舉例:

#1. multiprocessing.Pool下的apply #發起同步呼叫後,
就在原地等著任務結束,根本不考慮任務是在計算還是在io阻塞,總之就是一股腦地等任務結束
#2. concurrent.futures.ProcessPoolExecutor().submit(func,).result()
#3. concurrent.futures.ThreadPoolExecutor().submit(func,).result()

簡單一句話就是:呼叫者呼叫了一個功能時呼叫者要等著被呼叫者執行完畢,無論被呼叫者是在阻塞還是非阻塞狀態,才能繼續進行自己的任務

非同步

非同步的概念和同步相對。呼叫在發出之後,這個呼叫就直接返回了,所以沒有返回結果.換句話說當一個非同步功能呼叫發出後,呼叫者不能立刻得到結果。但是這個時候被呼叫者可以去執行下面的程式碼而不是一味的等待。
另外需要強調的一點:
當該非同步功能完成後,被呼叫者可以通過狀態、通知或回撥來通知呼叫者。如果非同步功能用狀態來通知,那麼呼叫者就需要每隔一定時間檢查一次,效率就很低(有些初學多執行緒程式設計的人,總喜歡用一個迴圈去檢查某個變數的值,這其實是一 種很嚴重的錯誤)。如果是使用通知的方式,效率則很高,因為非同步功能幾乎不需要做額外的操作。至於回撥函式,其實和通知沒太多區別。

舉例:

#1. multiprocessing.Pool().apply_async() #發起非同步呼叫後,
並不會等待任務結束才返回,相反,會立即獲取一個臨時結果(並不是最終的結果,
可能是封裝好的一個物件)。
#2. concurrent.futures.ProcessPoolExecutor(3).submit(func,)
#3. concurrent.futures.ThreadPoolExecutor(3).submit(func,)

阻塞與非阻塞

阻塞

阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起(如遇到io操作)。呼叫執行緒只有在得到結果之後才會返回。函式只有在得到結果之後才會將阻塞的執行緒啟用。有人也許會把阻塞呼叫和同步呼叫等同起來,實際上他是不同的。對於同步呼叫來說,很多時候當前執行緒還是啟用的,只是從邏輯上當前函式沒有返回而已。

舉例:

1. 同步呼叫:apply一個累計1億次的任務,該呼叫會一直等待,直到任務返回結果為止,
但並未阻塞住(即便是被搶走cpu的執行許可權,那也是處於就緒態);
2. 阻塞呼叫:當socket工作在阻塞模式的時候,如果沒有資料的情況下呼叫recv函式,
則當前執行緒就會被掛起,直到有資料為止。

非阻塞

非阻塞和阻塞的概念相對應,非阻塞呼叫指在不能立刻得到結果之前也會立刻返回,同時該函式不會阻塞當前執行緒。

總結

  1. 同步與非同步針對的是函式/任務的呼叫方式:同步就是當一個程序發起一個函式(任務)呼叫的時候,一直等到函式(任務)完成,而程序繼續處於啟用(非阻塞)狀態。而非同步情況下是當一個程序發起一個函式(任務)呼叫的時候,不會等函式返回,而是繼續往下執行,當函式返回的時候通過狀態、通知、事件等方式通知程序任務完成。
  2. 阻塞與非阻塞針對的是程序或執行緒:阻塞是當請求不能滿足的時候就將程序掛起,而非阻塞則不會阻塞當前程序



作者:不_一
連結:https://www.jianshu.com/p/47ee57646369
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。