- 进程的概念
进程是程序在计算机上的一次执行活动。
进程可分为系统进程和用户进程。
所有正在运行的进程轮流使用CPU,任何一个时间点有且只有一个进程占用CPU。
- 进程与线程的区别
进程 > 线程
多进程使用CPU的多个核,适合运算密集型
多线程使用CPU的一个核,核心IO密集型
- python多进程 —— muiltiprocessing模块
python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程。Python提供了multiprocessing。
Multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
- 创建一个Process实例
p1 = multiprocessing.Process(target=func, args=(2,))
target=函数名字
args=函数所需的参数,以tuple形式传入,必须有逗号,注意单个参数的形式
multiprocessing的2个常用方法:
multiprocessing.cpu_count() # 1. 统计CPU总数 multiprocessing.active_children() # 2. 获取所有子进程
- Process实例的常用属性和方法
常用属性:
p1 = multiprocessing.Process(target=func, args=(2,)) p1.name # 进程名字 p1.pid # 进程ID
常用方法:
p1 = multiprocessing.Process(target=func, args=(2,)) p1.is_alive() # 判断进程是否存活 p1.run() # 启动进程(不常用) p1.start() # 启动进程,自动调用run()方法(常用) p1.join(timeout=5) # 等待进程结束或直到超时(5s)
- 习题1
1 import multiprocessing 2 import time 3 4 5 def worker(args, interval): 6 print("start worker {0}".format(args)) 7 time.sleep(interval) 8 print("end worker {0}".format(args)) 9 10 def main(): 11 print("start main") 12 p1 = multiprocessing.Process(target=worker, args=(1, 1)) 13 p2 = multiprocessing.Process(target=worker, args=(2, 2)) 14 p3 = multiprocessing.Process(target=worker, args=(3, 3)) 15 p1.start() 16 p2.start() 17 p3.start() 18 print("end main") 19 20 if __name__ == '__main__': 21 main()
start main end main start worker 1 start worker 2 start worker 3 end worker 1 end worker 2 end worker 3
- 习题2
1 import multiprocessing 2 import time 3 4 def worker(args, interval): 5 print("start worker {0}".format(args)) 6 time.sleep(interval) 7 print("end worker {0}".format(args)) 8 9 def main(): 10 print("start main") 11 p1 = multiprocessing.Process(target=worker, args=(1, 1)) 12 p2 = multiprocessing.Process(target=worker, args=(2, 2)) 13 p3 = multiprocessing.Process(target=worker, args=(3, 3)) 14 p1.start() 15 p1.join(timeout=0.5) 16 p2.start() 17 p3.start() 18 print("the number of CPU is: {0}".format(multiprocessing.cpu_count())) 19 for p in multiprocessing.active_children(): 20 print("The name of active children is: {0}, pid is: {1} is alive".format(p.name, p.pid)) 21 print("end main") 22 23 if __name__ == '__main__': 24 main()
start main start worker 1 the number of CPU is: 4 The name of active children is: Process-1, pid is: 1348 is alive The name of active children is: Process-3, pid is: 1350 is alive The name of active children is: Process-2, pid is: 1349 is alive end main start worker 2 start worker 3 end worker 1 end worker 2 end worker 3
- Lock组件
使用多进程来读写文件时,读和写不能同时进行,为了这种多个进程共享同一资源的场景不出问题,引入了锁机制。
锁有两种状态:被锁(locked)和没有被锁(unlocked)。拥有acquire()和release()两种方法,并且遵循一下的规则:
- 如果一个锁的状态是unlocked,调用acquire()方法改变它的状态为locked
- 如果一个锁的状态是locked,acquire()方法将会阻塞,直到另一个线程调用release()方法释放了锁;
- 如果一个锁的状态是unlocked调用release()会抛出RuntimeError异常;
- 如果一个锁的状态是locked,调用release()方法改变它的状态为unlocked。
- 习题3
1 import multiprocessing 2 import time 3 4 def add1(lock, value, number): 5 with lock: 6 print("start add1 number= {0}".format(number)) 7 for i in range(1, 5): 8 number += value 9 time.sleep(0.3) 10 print("number = {0}".format(number)) 11 12 def add3(lock, value, number): 13 lock.acquire() 14 print("start add3 number= {0}".format(number)) 15 try: 16 for i in range(1, 5): 17 number += value 18 time.sleep(0.3) 19 print("number = {0}".format(number)) 20 except Exception as e: 21 raise e 22 finally: 23 lock.release() 24 pass 25 26 if __name__ == '__main__': 27 print("start main") 28 number = 0 29 lock = multiprocessing.Lock() 30 p1 = multiprocessing.Process(target=add1, args=(lock, 1, number)) 31 p3 = multiprocessing.Process(target=add3, args=(lock, 3, number)) 32 p1.start() 33 p3.start() 34 print("end main")
start main end main start add1 number= 0 number = 1 number = 2 number = 3 number = 4 start add3 number= 0 number = 3 number = 6 number = 9 number = 12
- 多进程间可共享内存
multiprocessing模块提供了共享内存的操作。
一般的变量在进程之间是无法通信的,multiprocessing提供了Value和Array模块,实现了进程间的数据共享。
Python中还提供了强大的Manager模块专门来做数据共享,其支持的类型非常多,包括Value, Array, list, dict, Queue, Lock等。
- 习题4
1 import multiprocessing 2 from multiprocessing import Value, Array, Manager 3 import time 4 5 6 def add1(value, number): 7 print("start add1 number= {0}".format(number.value)) 8 for i in range(1, 5): 9 number.value += value 10 print("number = {0}".format(number.value)) 11 12 def add3(value, number): 13 print("start add3 number= {0}".format(number.value)) 14 try: 15 for i in range(1, 5): 16 number.value += value 17 print("number = {0}".format(number.value)) 18 except Exception as e: 19 raise e 20 21 if __name__ == '__main__': 22 print("start main") 23 number = Value('d', 0) 24 p1 = multiprocessing.Process(target=add1, args=(1, number)) 25 p3 = multiprocessing.Process(target=add3, args=(3, number)) 26 p1.start() 27 p3.start() 28 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