同步異步,阻塞非阻塞,并發并行,線程進程協程

同步異步與阻塞非阻塞的理解:

概念比較抽象,結合具體的例子比較容易理解,比如小明燒了一壺水準備泡咖啡來喝:

1.同步阻塞:小明在燒水的時候,什么也不干,就等著水開,水開了以后再去泡咖啡,這叫同步阻塞

2.同步非阻塞:小明仍然在用壺燒水,不過此時他不在傻傻的等著水開,而是先去玩了把王者榮耀,每當自己死了,就過來看看水開了沒有,如果水開了就去泡咖啡,這叫同步非阻塞。

3.異步阻塞:其實異步就不存在阻塞了,一會在說明

4.異步非阻塞:小明仍然燒水煮咖啡,此時他不傻乎乎的等待結果,而是先去做別的事情,等他聽到了水壺的響聲以后,過來直接取燒開的水來泡咖啡,這種叫異步非阻塞。

同步:是指程序發起一個請求之后,直到請求返回結果之后,才進行下一步操作,簡單說就是一件事做完才能去做下一件事,比如我發起一個網絡請求查詢一個人的身份證,然后根據身份證查看這個人的詳細信息。那么我查詢詳細信息的操作需要等待查詢身份證的操作,那么此時查詢身份證的操作就是一個同步操作。

異步:異步很明顯是與同步相對,二者的區別在于是否需要等待某操作的返回結果。簡單來說,我們還是一個網絡請求,如果我們此時不需要依賴這個請求的結果就能進行后續操作,那么此時這個網絡請求就是一個異步操作。

當一個異步操作發出后,調用者在沒有得到結果之前,可以繼續執行后續操作。這就是異步。

阻塞:

阻塞的概念往往伴隨著線程。阻塞一般是指:在調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之后才會被喚醒執行后續的操作。

非阻塞:

那么非阻塞,毫無疑問是阻塞的反向操作。非阻塞式的調用指:在結果沒有返回之前,該調用不會阻塞住當前線程。

感覺阻塞/非阻塞和同步/異步有異曲同工的地方?

其實,這兩者存在本質的區別,面向的對象是不同的。

阻塞/非阻塞:進程/線程需要操作的數據如果尚未就緒,是否妨礙了當前進程/線程的后續操作。

同步/異步:數據如果尚未就緒,是否需要等待數據結果。

二、并發和并行

二者的區分其實就在于四個字:是否同時。

并發:當有多個線程在操作時,如果系統只有一個CPU,操作系統只能把CPU運行時間劃分成若干個時間段,再將時間段分配給各個線程執行,在一個時間段的快速的切換不同的線程代碼運行。

并行:當系統有多個CPU時,可以存在當一個CPU執行一個線程時,另一個CPU可以執行另一個線程,兩個線程互不搶占CPU資源,可以同時進行。

再舉個例子來形象的理解,

小明吃飯吃到一半,電話來了,小明一直到吃完了以后才去接。既不并發也不并行

小明吃飯吃到一半,電話來了,小明停了下來接了電話,接完后繼續吃飯。這是并發

小名吃飯吃到一半,電話來了,小明一邊打電話一邊吃飯。這是并行


三、python中的線程進程和協程

先用一句話來總結:一個程序就是一個進程,進程可以擁有多個線程,而協程是微線程。

1.進程:進程一般由程序、數據集、進程控制塊三部分組成。我們編寫的程序用來描述進程要完成哪些功能以及如何完成;數據集則是程序在執行過程中所需要使用的資源;進程控制塊用來記錄進程的外部特征,描述進程的執行變化過程,系統可以利用它來控制和管理進程,它是系統感知進程存在的唯一標志。比較抽象但容易理解,python的進程通過multiprocessing.process()來創建。

Pool類描述了一個工作進程池,他有幾種不同的方法讓任務卸載工作進程。進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,如果進程池序列中沒有可供使用的進進程,那么程序就會等待,直到進程池中有可用進程為止。

我們可以用Pool類創建一個進程池, 展開提交的任務給進程池。

2.線程:線程是屬于進程的,線程運行在進程空間內,同一進程所產生的線程共享同一內存空間,當進程退出時該進程所產生的線程都會被強制退出并清除。線程可與屬于同一進程的其它線程共享進程所擁有的全部資源,線程是應用程序工作的最小單元。python的線程是通過threading.Thread()來創建的

GIL:(global interpreter lock)全局解釋器鎖:這是CPython所獨有的而且我們用的也大多數是CPython所以在Cpython中,多線程其實是偽多線程,只是因為線程切換速度很快一般發覺不到而已,但他確實存在,所以在實際中能用多進程盡量不要用多線程

3.協程:

線程和進程的操作是由程序觸發系統接口,最后的執行者是系統;協程的操作則是程序員。

協程存在的意義:對于多線程應用,CPU通過切片的方式來切換線程間的執行,線程切換時需要耗時(保存狀態,下次繼續)。協程,則只使用一個線程,在一個線程中規定某個代碼塊執行順序。

協程的適用場景:當程序中存在大量不需要CPU的操作時(IO),適用于協程;

event loop是協程執行的控制點, 如果你希望執行協程, 就需要用到它們。

子程序(函數)在執行過程中可以中斷去執行別的子程序;別的子程序也可以中斷回來繼續執行之前的子程序,那么很容易想到Python的yield,顯然yield是可以實現這種切換的。python用到協程的標志之一就是yield

協程的優點:

  (1)無需線程上下文切換的開銷,協程避免了無意義的調度,由此可以提高性能(但也因此,程序員必須自己承擔調度的責任,同時,協程也失去了標準線程使用多CPU的能力)

  (2)無需原子操作鎖定及同步的開銷

  (3)方便切換控制流,簡化編程模型

  (4)高并發+高擴展性+低成本:一個CPU支持上萬的協程都不是問題。所以很適合用于高并發處理。

協程的缺點:

  (1)無法利用多核資源:協程的本質是個單線程,它不能同時將 單個CPU 的多個核用上,協程需要和進程配合才能運行在多CPU上.當然我們日常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應用。

  (2)進行阻塞(Blocking)操作(如IO時)會阻塞掉整個程序

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 我們終究愛不到終點(三十三) 這兩個牙刷,我無法抉擇。在那發呆…… 老板走過來,“不知道選哪個?” “吶,這兩個看...
    倚愷閱讀 257評論 0 0
  • 這是一部影像風格無比侯孝賢的電影,然而它不是侯孝賢的作品,它是一部寓言,關于電影的寓言。 一個在電影場長大的孩子,...
    勒尤閱讀 230評論 0 0