Python並行編程(七):多進程的基本使用和與多線程的差別

進程

 因爲GIL的存在,Python中的多線程其實並非真正的多線程,若是想要充分地使用多核CPU的資源,在Python中大部分狀況須要使用多進程。Python提供了很是好用的多進程模塊multiprocessing,只須要定義一個函數,Python會完成其餘全部事情。藉助這個模塊,能夠輕鬆完成從單進程到併發執行的轉換。multiprocessing支持子進程、通訊和共享數據、執行不一樣形式的同步,提供了ProcessLockQueuePipe等組件。python

  multiprocessing模塊是Python中的多進程模塊。與threading.Thread相似,它能夠利用multiprocessing.Process對象來建立一個進程。該進程能夠運行在Python程序內部編寫的函數。該Process對象與Thread對象的用法相同,也有start(),run(), join()的方法。此外multiprocessing模塊中也有Lock/Event/Semaphore/Condition類 (這些對象能夠像多線程那樣,經過參數傳遞給各個進程),用以同步進程,其用法與threading模塊中的同名類一致。因此,multiprocessing的很大一部份與threading使用同一套API,只不過換到了多進程的情境。 固然多進程的定義方式也和多線程相似,即兩種方式:多線程

目標函數實例化定義新的進程:

# 導入多進程模塊
from multiprocessing import Process

# os.getpid() 獲取當前進程的id
import os

def run_proc(name):
    print('{} child process is {}'.format(name, os.getpid()))

if __name__ == '__main__':
    print("Parent process is {}".format(os.getpid()))
    p = Process(target=run_proc, args=('test', ))
    print('child process will start...')
    p.start()
    p.join()

    print('child process end.')
複製代碼

運行截圖以下: 併發

運行截圖

繼承類來定義新的進程

from multiprocessing import Process
import os


class RunProc(Process):
    def __init__(self, name):
        Process.__init__(self)

        self.name = name

    def run(self):
        print('{} child process is {}'.format(self.name, os.getpid()))


if __name__ == "__main__":
    print("Parent process is {}".format(os.getpid()))
    p = RunProc('test')
    print('child process will start...')
    p.start()
    p.join()

    print('child process end.')
複製代碼

運行結果以下: 函數

運行截圖
咱們能夠看見,多進程的使用方式和多線程幾乎同樣,好比如下: Process([group [, target [, name [, args [, kwargs]]]]])

  • group: 線程組,目前尚未實現,庫引用中提示必須是None;
  • target: 要執行的方法;
  • name: 進程名;
  • args/kwargs: 要傳入方法的參數。

實例方法:測試

  • is_alive():返回進程是否在運行。
  • join([timeout]):阻塞當前上下文環境的進程程,直到調用此方法的進程終止或到達指定的timeout(可選參數)。
  • start():進程準備就緒,等待CPU調度
  • run():strat()調用run方法,若是實例進程時未制定傳入targetstart執行默認的· run()方法。
  • terminate():無論任務是否完成,當即中止工做進程

屬性:spa

  • daemon:和線程的setDeamon功能同樣
  • exitcode(進程在運行時爲None、若是爲–N,表示被信號N結束)
  • name:進程名字。
  • pid:進程號。

進程的獨立性:

和線程不同的是,進程之間相互獨立,咱們能夠從全局變量的修改窺見一些:線程

from multiprocessing import Process

# 測試數據
ex_list = 'Hello World'

# 修改數據進程
def revise_data():
    global ex_list

    # 修改全局變量
    ex_list = ex_list + ' with write revise_data process.'
    print('wirte result:', ex_list)

# 查看數據進程
def view_data():
    print(ex_list)

if __name__ == "__main__":
    process_revise = Process(target=revise_data)
    process_view = Process(target=view_data)

    process_revise.start()

    # 主進程等待寫入進程執行完成之後代碼 再繼續往下執行
    process_revise.join()

    process_view.start()
    process_view.join()

    print("process end.")
複製代碼

運行截圖以下: code

運行結果
咱們定義了兩個進程,分別用來修改全局變量和查看修改後的數據,咱們看見雖然修改的進程已經成功修改了變量,可是在查看進程中全局變量仍然是原來的值,即進程之間是不共享全局變量的,即建立子進程實際上是對主進程進行拷貝,進程之間相互獨立,訪問的全局變量不是同一個,因此進程之間不共享全局變量。
相關文章
相關標籤/搜索