上一篇文章介紹了線程的使用。然而 Python 中由于
Global Interpreter Lock
(全局解釋鎖 GIL )的存在,每個線程在在執行時需要獲取到這個 GIL ,在同一時刻中只有一個線程得到解釋鎖的執行, Python 中的線程并沒有真正意義上的并發執行,多線程的執行效率也不一定比單線程的效率更高。 如果要充分利用現代多核 CPU 的并發能力,就要使用 multipleprocessing 模塊了。
0x01 multipleprocessing
與使用線程的 threading 模塊類似,
multipleprocessing
模塊提供許多高級 API 。最常見的是 Pool 對象了,使用它的接口能很方便地寫出并發執行的代碼。
關于 Pool 下文中還會提到,這里我們先來看 Process 。
Process
要創建一個進程可以使用 Process 類,使用 start() 方法啟動進程。
進程池
正如開篇提到的
multiprocessing
模塊提供了 Pool 類可以很方便地實現一些簡單多進程場景。 它主要有以下接口
- apply(func[, args[, kwds]])
- 執行 func(args,kwds) 方法,在方法結束返回前會阻塞。
- apply_async(func[, args[, kwds[, callback[, error_callback]]]])
- 異步執行 func(args,kwds) ,會立即返回一個 result 對象,如果指定了 callback 參數,結果會通過回調方法返回,還可以指定執行出錯的回調方法 error_callback()
- map(func, iterable[, chunksize])
- 類似內置函數 map() ,可以并發執行 func ,是同步方法
- map_async(func, iterable[, chunksize[, callback[, error_callback]]])
- 異步版本的 map
- close()
- 關閉進程池。當池中的所有工作進程都執行完畢時,進程會退出。
- terminate()
- 終止進程池
- join()
-
等待工作進程執行完,必需先調用 close() 或者 terminate()
map_async() 和 apply_async() 執行后會返回一個 class multiprocessing.pool.AsyncResult 對象,通過它的 get() 可以獲取到執行結果, ready() 可以判斷 AsyncResult 的結果是否準備好。
進程間數據的傳輸
multiprocessing 模塊提供了兩種方式用于進程間的數據共享:隊列( Queue )和管道( Pipe )
Queue 是線程安全,也是進程安全的。使用 Queue 可以實現進程間的數據共享,例如下面的 demo 中子進程 put 一個對象,在主進程中就能 get 到這個對象。 任何可以序列化的對象都可以通過 Queue 來傳輸。
Pipe() 返回一對通過管道連接的 Connection 對象。這兩個對象可以理解為管道的兩端,它們通過 send() 和 recv() 發送和接收數據。
需要注意的是,兩個進程不能同時對一個連接對象進行 send 或 recv 操作。
同步
我們知道線程間的同步是通過鎖機制來實現的,進程也一樣。
有鎖的代碼將每秒依次打印
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
如果執行無鎖的代碼,則在我的電腦上執行結果是這樣的
hello worldhello world? 0
1
hello world 2
hello world 3
hello world 4
除了 Lock ,還包括 RLock 、 Condition 、 Semaphore 和 Event 等進程間的同步原語。其用法也與線程間的同步原語很類似。 API 使用可以參考文末中引用的文檔鏈接。
在工程中實現進程間的數據共享應當優先使用 隊列或管道。
0x02 總結
本文對 multiprocessing 模塊中常見的 API 作了簡單的介紹。講述了 Process 和 Pool 的常見用法,同時介紹了進程間的數據方式:隊列和管道。最后簡單了解了進程間的同步原語。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
