入門Python多線程/多進程編程
微信公眾號:python技術交流
如有問題或建議,請公眾號留言
線程和進程
計算機,用於計算的機器。計算機的核心是CPU,在現在多核心的電腦很常見了。為了充分利用cpu核心做計算任務,程序實現了多線程模型。通過多線程實現多任務的並行執行。
現在的操作系統多是多任務操作系統。每個應用程序都有一個自己的進程。操作系統會為這些進程分配一些執行資源,例如內存空間等。在進程中,又可以創建一些線程,他們共享這些內存空間,並由操作系統調用,以便並行計算。
線程創建之後,是有多個狀態的,大概的關係如下圖:
Python 多線程使用
Python提供兩個模塊進行多線程的操作,分別是thread和threading,前者是比較低級的模塊,用於更底層的操作,一般應有級別的開發不常用。後者則封裝了更多高級的介面,類似java的多線程風格,提供run方法和start調用。
執行的結果如下:
通過執行結果可以看到,啟動兩個進程,然後列印主進程退出,主進程等待兩個線程退出之後,整個程序退出。
當我們把注釋的這一段代碼打開:
然後,再次執行之後,我們會看到這樣的結果:
由此,我們可以看到,thread執行join之後,方法將會等待直到線程結束。這將阻塞正在調用的線程,直到被調用join()方法的線程結束。
如果修改上述的代碼,在新建thread之後,添加如下兩行代碼:
然後再次執行,得到的結果如下:
可以看到,daemon = True的時候,進程是守護進程,在主進程退出之後,就會直接退出,不會等待子進程執行完成。
GIL 全局解釋器鎖
在python的世界裡,對於線程,就不得不說一句GIL(全局解釋器鎖)。GIL的存在讓python的多線程多少有點雞肋了。Cpython的線程是操作系統原生的線程在解釋器解釋執行任何Python代碼時,都需要先獲得這把鎖才行,在遇到 I/O 操作時會釋放這把鎖。因為python的進程做為一個整體,解釋器進程內只有一個線程在執行,其它的線程都處於等待狀態等著GIL的釋放。
因此,在Python中,多線程最好用來處理I/O相關的操作,而當我們遇到計算密集型的操作的時候,Python推薦的時候使用多進程來進行處理,下面我們介紹下多進程的編程。
multiprocess 模塊
multiprocessing包是Python中的多進程管理包。與threading.Thread類似,它可以利用multiprocessing.Process對象來創建一個進程。該進程可以運行在Python程序內部編寫的函數。該Process對象與Thread對象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition類 (這些對象可以像多線程那樣,通過參數傳遞給各個進程),用以同步進程,其用法與threading包中的同名類一致。所以,multiprocessing的很大一部份與threading使用同一套API,只不過換到了多進程的情境。
先看如下一個例子:
執行的結果如下:
Process的使用示例如下:
具體的執行結果,大家可以自己執行的過程中看下。
多個進程之間是可以進行通信的,目前支持兩種數據交互方式,Queues和Pipe.
Pipe function默認創建的是一個全雙工的管道,能夠互相之間發送和接收數據。
在多進程執行的過程中,我們也可以非同步的進行執行,如果我們關心執行結果,那麼我們就可以對拿到的結果進行再次處理,如下面的demo程序:
執行結果如下:
上面的操作中,都使用的是多進程來進行並發處理,該模塊中同樣包含了對多線程的封裝,只需要對上述代碼做如下變動:
其他操作方式和多進程相同。
本文對進程間的通信以及相關的鎖的機制沒有進行深入的探討,在後續文章中,會進行講解。
※用Python進行機器學習
※一篇文章讀懂Python賦值與拷貝
TAG:Python |