進程是程序在計算機上的一次執行活動。當你運行一個程序,你就啓動了一個進程。顯然,程序是死的(靜態的),進程是活的(動態的)。進程能夠分爲系統進程和用戶進程。凡是用於完成操做系統的各類功能的進程就是系統進程,它們就是處於運行狀態下的操做系統自己;用戶進程就沒必要我多講了吧,全部由你啓動的進程都是用戶進程。進程是操做系統進行資源分配的單位。
在操做系統的管理下,全部正在運行的進程輪流使用CPU,每一個進程容許佔用CPU的時間很是短(好比10毫秒),這樣用戶根本感受不出來CPU是在輪流爲多個進程服務,就好象全部的進程都在不間斷地運行同樣。但實際上在任何一個時間內有且僅有一個進程佔有CPU。html
進程(process)和線程(thread)
單個CPU一次只能運行一個任務;在任一時刻,CPU老是運行一個進程,其餘進程處於非運行狀態;
一個進程能夠包含多個線程;
進程沒有任何共享狀態,進程修改的數據,改動僅限於該進程內;
一個進程的內存空間是共享的,每一個線程均可以使用這些共享內存;
一個線程使用某些共享內存時,其餘線程必須等它結束才能使用這一塊內存;防止多個線程同時讀寫某一塊內存區域,採用互斥鎖(Mutual exclusion,縮寫Mutex);
某些內存區域只能供給固定數目的線程使用,此時經過信號量(Semaphore)保證多個線程不會互相沖突;
多進程形式,運行多個任務同時運行;多線程形式,容許單個任務分紅不一樣的部分運行;
多線程使用的是cpu的一個核,適合io密集型;
多進程使用的是cpu的多個核,適合運算密集型。
在linux中可使用ps -efL查看進程和線程ID。以memcached進程爲例,輸出結果以下python
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@VM_0_4_centos ~]# ps -efL |grep memcached root 24421 1 24421 0 10 May19 ? 00:00:03 memcached -d -u root root 24421 1 24422 0 10 May19 ? 00:00:01 memcached -d -u root root 24421 1 24423 0 10 May19 ? 00:00:00 memcached -d -u root root 24421 1 24424 0 10 May19 ? 00:00:00 memcached -d -u root root 24421 1 24425 0 10 May19 ? 00:00:00 memcached -d -u root root 24421 1 24426 0 10 May19 ? 00:00:00 memcached -d -u root root 24421 1 24427 0 10 May19 ? 00:00:00 memcached -d -u root root 24421 1 24428 0 10 May19 ? 00:00:00 memcached -d -u root root 24421 1 24429 0 10 May19 ? 00:00:09 memcached -d -u root root 24421 1 24430 0 10 May19 ? 00:00:00 memcached -d -u root root 32169 31101 32169 0 1 23:23 pts/0 00:00:00 grep --color=auto memcached |
第一行UID
(用戶ID),第二行爲PID
(進程ID),第三行PPID
(父進程ID),第四行LWP
(線程ID)。
從示例能夠看出,進程24421子進程有10個,對應線程ID分別爲24421-24430。linux
python中的多線程沒法利用多核優點,若要充分使用多核CPU資源,在python中大部分狀況使用多進程。python提供了很是好用的多進程包multiprocessing。
multiprocessing模塊用來開啓子進程,並在子進程中執行咱們定製的任務(好比函數),該模塊與多線程模塊threading的編程接口相似。
multiprocessing模塊的功能衆多:支持子進程、通訊和共享數據、執行不一樣形式的同步,提供了Process、Queue、Pipe、Lock等組件。編程
建立一個Process對象centos
1 |
p = multiprocessing.Process(target=worker_1, args=(2, )) |
參數
target:函數名字
args:函數須要的參數,以tuple的形式傳入(單個元素的tuple必須有逗號)安全
方法
p.is_alive() 判斷進程p是否存活,是返回True
p.run() 啓動進程,它去調用target指定的函數
p.start() 啓動進程,它會自動調用run方法,推薦使用start
p.join(timeout) 主線程等待p終止(主線程處於等的狀態,p處於運行狀態)。p.join只能join使用start開啓的進程,不能join使用run開啓的進程
p.terminate() 強制進程p退出,不會進行任何清理操做,若是p建立了子進程,該子進程就變成了殭屍進程多線程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import multiprocessing import time def worker(args, interval): print("start worker {0}".format(args)) time.sleep(interval) print("end worker {0}".format(args)) def main(): print("start main") p1 = multiprocessing.Process(target=worker, args=(1, 1)) p2 = multiprocessing.Process(target=worker, args=(2, 2)) p3 = multiprocessing.Process(target=worker, args=(3, 3)) p1.start() p2.start() p3.start() print("end main") if __name__ == '__main__': main() |
輸出結果memcached
1 2 3 4 5 6 7 8 |
start main end main start worker 1 start worker 2 start worker 3 end worker 1 end worker 2 end worker 3 |
multprocessing用到的兩個方法
cpu_count():統計cpu總數
active_children():得到全部子進程函數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import multiprocessing import time def worker(args, interval): print("start worker {0}".format(args)) time.sleep(interval) print("end worker {0}".format(args)) def main(): print("start main") p1 = multiprocessing.Process(target=worker, args=(1, 1)) p2 = multiprocessing.Process(target=worker, args=(2, 2)) p3 = multiprocessing.Process(target=worker, args=(3, 3)) p1.start() p1.join(timeout=0.5) #此處保證了p1優先執行 p2.start() p3.start() print("the number of CPU is: {0}".format(multiprocessing.cpu_count())) for p in multiprocessing.active_children(): print("The name of active children is: {0}, pid is: {1} is alive".format(p.name, p.pid)) print("end main") if __name__ == '__main__': main() |
輸出結果ui
1 2 3 4 5 6 7 8 9 10 11 12 |
start main start worker 1 the number of CPU is: 4 The name of active children is: Process-1, pid is: 25360 is alive The name of active children is: Process-2, pid is: 24500 is alive The name of active children is: Process-3, pid is: 26100 is alive end main start worker 3 start worker 2 end worker 1 end worker 2 end worker 3 |
當咱們用多進程來讀寫文件的時候,若是一個進程是寫文件,一個進程是讀文件,若是兩個文件同時進行,確定是不行的,必須是文件寫結束之後,才能夠進行讀操做。或者是多個進程在共享一些資源的時候,同時只能有一個進程進行訪問,那就要有一個鎖機制進行控制。
下面使用2個進程分別進行+1
和+3
操做爲例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import time import multiprocessing def add(value, number): print("start add{0} number= {1}".format(value, number)) for i in range(1, 3): number += value time.sleep(0.3) print("number = {0}".format(number)) if __name__ == '__main__': print("start main") number = 0 p1 = multiprocessing.Process(target=add, args=(1, number)) p3 = multiprocessing.Process(target=add, args=(3, number)) p1.start() p3.start() print("end main") |
輸出結果
1 2 3 4 5 6 7 8 |
start main end main start add1 number= 0 start add3 number= 0 number = 1 number = 3 number = 2 number = 6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import time import multiprocessing def add(lock, value, number): with lock: print("start add{0} number= {1}".format(value, number)) for i in range(1, 3): number += value time.sleep(0.3) print("number = {0}".format(number)) if __name__ == '__main__': print("start main") number = 0 lock = multiprocessing.Lock() p1 = multiprocessing.Process(target=add, args=(lock, 1, number)) p3 = multiprocessing.Process(target=add, args=(lock, 3, number)) p1.start() p3.start() print("end main") |
輸出結果
1 2 3 4 5 6 7 8 |
start main end main start add1 number= 0 number = 1 number = 2 start add3 number= 0 number = 3 number = 6 |
鎖的獲取可使用lock.acquire()
獲取,lock.release()
釋放
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def add(lock, value, number): lock.acquire() print("start add3 number= {0}".format(number)) try: for i in range(1, 5): number += value time.sleep(0.3) print("number = {0}".format(number)) except Exception as e: raise e finally: lock.release() pass |
通常變量在進程之間是無法進行通信的,可是multiprocessing提供了Value
和Array
模塊,能夠在不一樣的進程中使用同一變量。Value
和Array
結構內部都實現了鎖機制,所以多進程是安全的。
Value和Array都須要設置其中存放值的類型,d是double類型,i是int類型。類型設置和array
模塊的值相似,更多的類型能夠點擊array — Efficient arrays of numeric values查看。
上面的示例中,兩個進程執行後number結果分別爲2和6,假如兩個進程能夠共享變量,name輸出結果將會是8。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import multiprocessing from multiprocessing import Value def add(value, number): print("start add{0} number= {1}".format(value, number.value)) for i in range(1, 3): number.value += value print("number = {0}".format(number.value)) if __name__ == '__main__': print("start main") number = Value('d', 0) #使用Value建立變量 p1 = multiprocessing.Process(target=add, args=(1, number)) p3 = multiprocessing.Process(target=add, args=(3, number)) p1.start() p3.start() print("end main") |
輸出結果
1 2 3 4 5 6 7 8 |
start main end main start add1 number= 0.0 start add3 number= 0.0 number = 1.0 number = 4.0 number = 5.0 number = 8.0 |
number最終結果是8,可是具體輸出結果每次執行可能存在差別。
更多關於multiprocessing
的內容能夠點擊multiprocessing — Process-based parallelism查看官方介紹。
Share