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()方法可以讓多進程像多線程一樣實現內存數據的共享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章