日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MultiProcess-MultiThread

發布時間:2025/6/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MultiProcess-MultiThread 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

聽到一些關于python多進程與多線的例子,感覺比較經典,把一些例子分享一下.

內容如下:

? ? Process、Thread、GIL、Process fork、Multiprocessing、Queue、ProcessPool、Multiprocess-Multithread comparison


(1) Process : 程序的一次執行(程序編寫完畢后代碼裝載入內存,系統分配資源運行)。每個進程有自己的內存空間、數據棧等,只能使用進 程間通訊,而不能直接共享信息?


(2) Thread線程:所有線程運行在同一個進程中,共享相同的運行環境。 每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口; 線程的運行可以被搶占(中斷),或暫時被掛起 (睡眠),讓其他線程運行(讓步);一個進程中的各個線程間共享同一片數據空間?


(3) 全局解釋器鎖GIL?

? ? GIL全稱全局解釋器鎖Global Interpreter Lock,GIL并不是Python的特性,它是在實現Python解析器(CPython) 所引入的一個概念。?

? ? GIL是一把全局排他鎖,同一時刻只有一個線程在運行。 毫無疑問全局鎖的存在會對多線程的效率有不小影響。甚至就幾乎等于Python是個單線程的程序。?

? ? multiprocessing庫的出現很大程度上是為了彌補thread庫因為 GIL而低效的缺陷。它完整的復制了一套thread所提供的接口方便遷移。唯一的不同就是它使用了多進程而不是多線程。每個進程有自己的獨立的GIL,因此也不會出現進程之間的GIL爭搶。?


多線程處理的例子:

from?threading?import?Thread import?time def?my_counter():i?=?0for?_?in?range(100000000):i?=i+1return?True def?main():thread_array?=?{}start_time?=?time.time()for?tid?in?range(2):t?=?Thread(target=my_counter())t.start()t.join()#以單線程、阻塞的方式順序運行兩次my_counter函數end_time?=?time.time()print("Total?time:{}").format(end_time?-?start_time)if?__name__=="__main__":main()

執行結果如下:

Total time:12.7875118256


from?threading?import?Thread import?time def?my_counter():i?=?0for?_?in?range(100000000):i?=?i+1return?True def?main():thread_array?=?{}start_time?=?time.time()for?tid?in?range(2):t?=?Thread(target=my_counter())t.start()thread_array[tid]?=?tfor?i?in?range(2):thread_array[i].join()#以多進程、并發的方式運行兩次my_counter函數end_time?=?time.time()print("Total?time:{}").format(end_time?-?start_time)if?__name__=="__main__":main()

執行結果如下:

Total time:15.8216409683


上述兩個例子的結果發現:單線程運行兩次函數的時間 ? 要比 ? 兩個線程同時運行函數的時間短(僅限于本例)。


(4) fork操作:?

調用一次,返回兩次。因為操作系統自動把當前進程(稱為父 進程)復制了一份(稱為子進程),然后分別在父進程和子進 程內返回。子進程永遠返回0,而父進程返回子進程的ID。子 進程只需要調用getppid()就可以拿到父進程的ID

例:

import?os print?'Process?(%s)?start?...'?%?os.getpid() pid=os.fork() if?pid==0:print?'I?am?child?process?(%s)?and?my?parent?is?(%s)'?%?(os.getpid(),os.getppid()) else:print?'I?(%s)?just?created?a?child?process?(%s).'?%?(os.getpid(),pid)

執行結果如下:

Process (16480) start ...

I (16480) just created a child process (16481).

I am child process (16481) and my parent is (16480)


(5) multiprocessing是跨平臺版本的多進程模塊,它提供了一個Process類來代表一個進程對象,下面是示例代碼:?

from?multiprocessing?import?Process import?time def?f(n):time.sleep(1)print?n*nif?__name__=="__main__":for?i?in?range(10):p=Process(target=f,args=[i,])p.start()#使用多進程并發的方式執行函數f

這個程序如果用單進程寫則需要執行10秒以上的時間, 而用多進程則啟動10個進程并行執行,只需要用1秒多的時間。多進程時,每個進程各自有各自的GIL。而同一進程中的多線程受到GIL的影響,效率返而會下降。


(6) Queue是多進程安全的隊列,可以使用Queue實現多進程之間的數據傳遞?

from?multiprocessing?import?Process,Queue import?time def?write(q):for?i?in?['A','B','C','D','E']:print?('Put?%s?to?queue'?%?i)q.put(i)time.sleep(0.5)def?read(q):while?True:v?=?q.get(True)print('get?%s?from?queue'?%v)if?__name__?==?'__main__':q?=?Queue()pw?=?Process(target=write,args=(q,))pr?=?Process(target=read,args=(q,))pw.start()pr.start()pr.join()pr.terminate()

輸出結果:

Put A to queue

get A from queue

Put B to queue

get B from queue

Put C to queue

get C from queue

Put D to queue

get D from queue

Put E to queue

get E from queue


(7) 進程池pool , 用于批量創建子進程,可以靈活控制子進程的數量?

from?multiprocessing?import?Pool import?time def?f(x):print?x*xtime.sleep(2)return?x*x if?__name__?==?'__main__':pool?=?Pool(processes=5)res_list?=?[]for?i?in?range(10):????????res?=?pool.apply_async(f,[i,])'''?以異步并行的方式啟動進程處理函數f,如果要同步等待的方式,可以在每次進程啟動之后調用res.get()方法,也可以使用Pool.apply'''print('-------:',i)res_list.append(res)pool.close()pool.join()for?r?in?res_list:print?'result',(r.get(timeout=5))

輸出結果如下:

('-------:', 0)

('-------:', 1)

('-------:', 2)

('-------:', 3)

('-------:', 4)

('0-------:', 5)

('-------:', 6)

('-------:', 7)

1

('-------:', 8)

('-------:', 9)

4

16

9

25

36

49

64

81

result 0

result 1

result 4

result 9

result 16

result 25

result 36

result 49

result 64

result 81

如果使用同步方式,處理函數時 必須等待 前一個處理的結束,所以如果將該程序換為同步方式,輸出結果則是順序的。


(8) 多進程與多線程的對比

from?multiprocessing?import?Process import?threading import?time lock?=?threading.Lock() def?run(info_list,n):lock.acquire()info_list.append(n)lock.release()print('%s'?%?info_list) if?__name__?==?'__main__':info?=?[]for?i?in?range(10):p?=?Process(target=run,args=[info,i])p.start()p.join()time.sleep(1)print('-----------------threading--------------')for?i?in?range(10):p?=?threading.Thread(target=run,args=[info,i])p.start()p.join()

輸出結果為:

[0]

[1]

[2]

[3]

[4]

[5]

[6]

[7]

[8]

[9]

-----------------threading--------------

[0]

[0, 1]

[0, 1, 2]

[0, 1, 2, 3]

[0, 1, 2, 3, 4]

[0, 1, 2, 3, 4, 5]

[0, 1, 2, 3, 4, 5, 6]

[0, 1, 2, 3, 4, 5, 6, 7]

[0, 1, 2, 3, 4, 5, 6, 7, 8]

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


多進程間數據不能直接共享,每次處理函數run的結果都不能繼承。而多線程間數據可以共享,但受到GIL的影響,run函數中在將數據追加到列表時,使用lock鎖,追回完畢再釋放lock,這樣避免沖突。

轉載于:https://blog.51cto.com/caiyuanji/1966279

總結

以上是生活随笔為你收集整理的MultiProcess-MultiThread的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。