python並發執行之多進程

    多進程顧名思義程序啟動的時候運行多個進程,每個進程啟動一條線程進行程序處理。 沒啟動一個進程就要單獨劃分一塊內存資源。就像工廠的廠房。為了提高效率每多添加一條生產線就要單獨再蓋一個廠房。每個廠房相互是獨立的。所以啟動多進程是很消耗資源的,畢竟廠房蓋多了廠區就沒地方給其他設施用了。

    多進程的代碼實現方法和多線程的函數方式很類似

#!/usr/bin/env python  # -*-coding:utf-8-*-  from multiprocessing import Process  #引用的模塊變成了多進程模塊  def foo(i):      print 'say hi',i  for i in range(10):      """      同時啟動10個進程,把Process()實例化給p      調用p.start()方法啟動每個進程      """      p = Process(target=foo,args=(i,))      p.start()

上面提到了多進程之間數據是相互獨立的,我們來寫一段代碼測試一下

#!/usr/bin/env python  #coding:utf-8     from multiprocessing import Process     li = []     def foo(i):  #向列表中加入當前的進程序列號      li.append(i)      print 'say hi',li      for i in range(10):      p = Process(target=foo,args=(i,))      p.start()         print 'ending',li

上面的代碼運行結果是

[wgw@mail ~]$ python test.py   say hi [0]  say hi [1]  say hi [2]  say hi [3]  say hi [4]  say hi [5]  say hi [6]  say hi [7]  say hi [8]  ending []  say hi [9]

    注意看ending [] 這一列。通過代碼我們得知每個一個派生的子進程都會調用foo()函數並將自己的進程運行序列號添加到li表中。但是當最後我們要查看li[]表裡存儲的內容,我們並沒有看到自己希望看到[0,1,2…9]的內容這是為什麼呢?這其實就是進程的內存相互獨立導致的。我們創建了進程0,那麼進程就複製了一個空列表li[],並把0追加到表裡。那麼對於進程0來說li列表的內容就是li[0]。但是進程1在啟動之後也和進程0一樣複製了一個空列表li[],對於進程1來說運行結束時候自己的列表li的內容就是li[1]。以此類推,啟動了10個子進程就複製了10個li[]空列表。每個進程中的列表都是相互獨立的,而程序的最後我們打印的是最主進程的那個li[]列表,這個列表沒有被操作過所以還是空的。通過這裡我們也可以得知,多進程的時候每個進程都要對資源進行複製。所以進程啟動多了會異常的消耗資源。

    如果我們要讓進程間數據同步,就需要藉助multiprocessing模塊中的Manager方法來管理特殊的列表或者字典。通過這種特殊方法來實現進程間數據的同步。看代碼

#!/usr/bin/env python  # -*-coding:utf-8-*-  from multiprocessing import Process,Manager  def foo(i,Manger_list):      """      函數要引用別Manger方法管理的特殊列表,這列表的      操作和標準列表是完全一致的。      """      Manger_list.append(i)      print 'say hi',li  if __name__=='__main__':      #定義一個空列表儲存生成的多進程句柄      p_list=[]      #實例化Manager方法      manager=Manager()      #聲明li是被manger管理的特殊列表      li = manager.list()      for i in range(10):          #將進程的啟動序列號和特殊列表賦值給foo()函數          p = Process(target=foo,args=(i,li))          p_list.append(p)      for p in p_list:          #執行多進程句柄,交給CPU調度          p.start()      for p in p_list:          #在最後一個子進程結束前,不能停止主進程          p.join()      #主進程結束後打印主進程中li列表的內容      print 'ending',li

這段代碼的運行結果是

say hi [0]  say hi [0, 7]  say hi [0, 7, 4]  say hi [0, 7, 4, 5]  say hi [0, 7, 4, 5, 6]  say hi [0, 7, 4, 5, 6, 2]  say hi [0, 7, 4, 5, 6, 2, 9]  say hi [0, 7, 4, 5, 6, 2, 9, 3]  say hi [0, 7, 4, 5, 6, 2, 9, 3, 8]  say hi [0, 7, 4, 5, 6, 2, 9, 3, 8, 1]  ending [0, 7, 4, 5, 6, 2, 9, 3, 8, 1]

從上面的結果就可以看出來,雖然進程執行結束的順序和啟動時候的順序不一樣了。但是每個子進程的執行結果都被追加到了同一個li列表中。並且最後主進程的li列表內容和子進程的的內容一致。說明通過multiprocessing.Manager()方法可以讓多進程像多線程一樣實現內存數據的共享。