Unix/Linux操做系統提供了一個fork()系統調用,它很是特殊。普通的函數調用,調用一次,返回一次,可是fork()調用一次,返回兩次,由於操做系統自動把當前進程(稱爲父進程)複製了一份(稱爲子進程),而後,分別在父進程和子進程內返回。子進程永遠返回0,而父進程返回子進程的ID。這樣作的理由是,一個父進程能夠fork出不少子進程,因此,父進程要記下每一個子進程的ID,而子進程只須要調用getppid()就能夠拿到父進程的ID。
進程是程序在計算機上的一次執行活動。當你運行一個程序,你就啓動了一個進程。顯然,程序是死的(靜態的),進程是活的(動態的)。進程能夠分爲系統進程和用戶進程。凡是用於完成操做系統的各類功能的進程就是系統進程,它們就是處於運行狀態下的操做系統自己。全部由你啓動的進程都是用戶進程。
通俗地講,在操做系統的管理下,全部正在運行的進程輪流使用CPU,每一個進程容許佔用CPU的時間很是短(好比10毫秒),這樣用戶根本感受不出來CPU是在輪流爲多個進程服務,就好象全部的進程都在不間斷地運行同樣。但實際上在任何一個時間內有且僅有一個進程佔有CPU。python
多進程和多線程的區別
多線程使用的是cpu的一個核,適合io密集型。
多進程使用的是cpu的多個核,適合運算密集型。多線程
Multiprocessing支持子進程,通訊,共享數據,執行不一樣形式的同步,提供了Process,Pipe, Lock等組件。函數
建立一個Process對象ui
p = multiprocessing.Process(target=worker_1, args=(2, ))
target = 函數名字
args = 函數須要的參數,以tuple的形式傳入
注意: 單個元素的tuple的表現形式(元素,)有一個逗號spa
multprocessing用到的兩個方法
cpu_count() 統計cpu總數
active_children() 得到全部子進程操作系統
is_alive() 判斷進程是否存活
run() 啓動進程
start() 啓動進程,會自動調用run方法,這個經常使用
join(timeout) 等待進程結束或者直到超時線程
name 進程名字
pid 進程的pidcode
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() 結果: start main end main start worker 1 start worker 3 start worker 2 end worker 1 end worker 2 end worker 3
p = multiprocessing.Process(target=, args=)
target 指定的是當進程執行時,須要執行的函數
args 是當進程執行時,須要給函數傳入的參數
注意: args必須是一個tuple, 特別是當函數須要傳入一個參數時 (1,)
p 表明的是一個多進程
p.is_alive() 判斷進程是否存活
p.run() 啓動進程
p.start() 啓動進程,他會自動調用run方法,推薦使用start
p.join(timeout) 等待子進程結束或者到超時時間後再繼續往下執行
p.terminate() 強制子進程退出
p.name 進程的名字
p.pid 進程的pidorm
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) 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() 結果: start main start worker 1 the number of CPU is: 4 The name of active children is: Process-3, pid is: 9056 is alive The name of active children is: Process-2, pid is: 5844 is alive The name of active children is: Process-1, pid is: 8428 is alive end main start worker 2 start worker 3 end worker 1 end worker 2 end worker 3
建立子進程時,只須要傳入一個執行函數和函數的參數,建立一個Process實例,用start()方法啓動,這樣建立進程比fork()還要簡單。對象
當咱們用多進程來讀寫文件的時候,若是一個進程是寫文件,一個進程是讀文件,若是兩個文件同時進行,確定是不行的,必須是文件寫結束之後,才能夠進行讀操做。或者是多個進程在共享一些資源的時候,同時只能有一個進程進行訪問,那就要有一個鎖機制進行控制。
當多個進程須要訪問共享資源的時候,Lock能夠用來避免訪問的衝突。主要用到了lock.acquire() 和lock.release()
import time import multiprocessing def add1(lock, value, number): with lock: print("start add1 number= {0}".format(number)) for i in range(1, 5): number += value time.sleep(0.3) print("number = {0}".format(number)) def add3(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 if __name__ == '__main__': print("start main") number = 0 lock = multiprocessing.Lock() p1 = multiprocessing.Process(target=add1, args=(lock, 1, number)) p3 = multiprocessing.Process(target=add3, args=(lock, 3, number)) p1.start() p3.start() print("end main") 結果: start main end main start add3 number= 0 number = 3 number = 6 number = 9 number = 12 start add1 number= 0 number = 1 number = 2 number = 3 number = 4
python的multiprocessing模塊也給咱們提供了共享內存的操做。
通常的變量在進程之間是無法進行通信的,multiprocessing給咱們提供了Value和Array模塊,他們能夠在不通的進程中共同使用,Value 和 Array 都須要設置其中存放值的類型,d 是 double 類型,i 是 int 類型。
import time import multiprocessing from multiprocessing import Value, Array, Manager def add1(value, number): print("start add1 number= {0}".format(number.value)) for i in range(1, 5): number.value += value print("number = {0}".format(number.value)) def add3(value, number): print("start add3 number= {0}".format(number.value)) try: for i in range(1, 5): number.value += value print("number = {0}".format(number.value)) except Exception as e: raise e if __name__ == '__main__': print("start main") number = Value('d', 0) p1 = multiprocessing.Process(target=add1, args=(1, number)) p3 = multiprocessing.Process(target=add3, args=(3, number)) p1.start() p3.start() print("end main") 結果: start main end main start add1 number= 0.0 number = 1.0 number = 2.0 number = 3.0 number = 4.0 start add3 number= 4.0 number = 7.0 number = 10.0 number = 13.0 number = 16.0