Python3中多進程和多線程的理論相關

一、多任務

之所以需要使用多進程或者是多線程,歸根結底就是為了進行多任務的處理。那么,多核CPU實現多任務原理和單核CPU的多任務原理是什么呢。

  • 單核CPU的多任務原理
    操作系統輪流讓各個任務交替執行。比如:QQ執行2毫秒,微信執行2毫秒....任務不斷反復切換,但又因為CPU調度執行速度太快了,導致我們感覺就是所有的任務都在同時執行。

  • 多核CPU實現多任務原理
    真正的多任務只能在多核CPU上實現,但是由于任務數量遠遠多于CPU的核心數量。所以,操作系統也會自動把很多任務輪流調度到每個核心上執行。

一般情況下任務數往往大于你的CPU核心數,所以會出現一顆CPU執行多個任務的情況。而這,又引出了并發和并行的概念

  • 并發和并行
    因為CPU的核心與任務數的不同。所以又出現了并發和并行的概念。

    并發:指的是任務數多余cpu核心數(你總有一顆CPU核心不止運行一個任務),所以只能通過操作系統的各種任務調度算法,實現用多個任務“一起”執行(因為切換任務的速度相當快,看上去一起執行而已。可以借助單核CPU的多任務原理來進行理解)

    并行:指的是任務數小于等于cpu核心數,即任務真的是一起執行的。效率最高。

  • 實現多任務的幾種方式:
    1、多進程模式
    2、多線程模式
    3、協程模式
    4、多進程+多線程模式

這里我們主要了解一下多進程和多線程的理論,后續將用代碼介紹Python3的多進程和多線程

二、進程和線程

  • 進程
    對于操作系統而言,一個任務就是一個進程。進程是系統中程序執行和資源分配的基本單位,每個資源都有自己的數據段、代碼段和堆棧段

  • 線程
    線程是操作系統能夠進行運算調度的最小單位(程序執行流的最小單元)。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。

  • 進程和線程的區別

(1)線程共享內存空間;進程的內存是獨立的

(2)同一個進程的線程之間可以直接交流;兩個進程想通信,必須通過一個中間代理來實現

(3)創建新線程很簡單; 創建新進程需要對其父進程進行一次克隆

(4)一個線程可以控制和操作同一進程里的其他線程;但是進程只能操作子進程

(5)改變主線程(如優先權),可能會影響其它線程;改變父進程,不影響子進程

  • 多進程和多線程的優缺點
    多進程
    缺點:密集CPU任務,需要充分使用多核CPU資源(服務器,大量的并行計算)的時候,用多進程。

    缺陷:多個進程之間通信成本高,切換開銷大。

    多線程
    優點:密集I/O任務(網絡I/O,磁盤I/O,數據庫I/O)使用多線程合適。

    缺陷:同一個時間切片只能運行一個線程,不能做到高并行,但是可以做到高并發。

  • 多線程在Python里是雞肋的說法
    首先來介紹一下GIL:GIL的全稱是Global Interpreter Lock(全局解釋器鎖),來源是python設計之初的考慮,為了數據安全所做的決定。一個線程想要執行,必須先拿到GIL。

    在Python多線程下,每個線程的執行方式:

    • 獲取GIL
    • 執行代碼直到sleep或者是python虛擬機將其掛起。
    • 釋放GIL

    在Python2.x里,GIL的釋放邏輯是當前線程遇見IO操作或者ticks計數達到100(ticks可以看作是Python自身的一個計數器,專門做用于GIL,每次釋放后歸零,這個計數可以通過 sys.setcheckinterval 來調整),進行釋放。

    而每次釋放GIL鎖,線程進行鎖競爭、切換線程,會消耗資源。并且由于GIL鎖存在,python里一個進程永遠只能同時執行一個線程(拿到GIL的線程才能執行),這就是為什么在多核CPU上,python的多線程效率并不高。

在一個python進程中,GIL只有一個。拿不到通行證的線程,就不允許進入CPU執行。所以,每個CPU在同一時間只能執行一個線程。而每個進程有各自獨立的GIL,所以多進程的執行效率優于多線程(僅僅針對多核CPU而言)。

  • 存在即合理,Python的多線程還是要進行分類討論
    CPU密集型代碼(各種循環處理、計數等等),在這種情況下,由于計算工作多,ticks計數很快就會達到閾值,然后觸發GIL的釋放與再競爭(多個線程來回切換當然是需要消耗資源的),所以python下的多線程對CPU密集型代碼并不友好。

    IO密集型代碼(文件處理、網絡爬蟲等),多線程能夠有效提升效率(單線程下有IO操作會進行IO等待,造成不必要的時間浪費,而開啟多線程能在線程A等待時,自動切換到線程B,可以不浪費CPU的資源,從而能提升程序執行效率)。所以python的多線程對IO密集型代碼比較友好。

多核多線程比單核多線程更差,原因是單核下的多線程,每次釋放GIL,喚醒的那個線程都能獲取到GIL鎖,所以能夠無縫執行,但多核下,CPU0釋放GIL后,其他CPU上的線程都會進行競爭,但GIL可能會馬上又被CPU0拿到,導致其他幾個CPU上被喚醒后的線程會醒著等待到切換時間后又進入待調度狀態,這樣會造成線程顛簸(thrashing),導致效率更低。

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