- 进程的概念
进程是程序在计算机上的一次执行活动。
进程可分为系统进程和用户进程。
所有正在运行的进程轮流使用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 mainend mainstart worker 1start worker 2start worker 3end worker 1end worker 2end 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 mainstart worker 1the number of CPU is: 4The name of active children is: Process-1, pid is: 1348 is aliveThe name of active children is: Process-3, pid is: 1350 is aliveThe name of active children is: Process-2, pid is: 1349 is aliveend mainstart worker 2start worker 3end worker 1end worker 2end 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 += value18 time.sleep(0.3)19 print("number = {0}".format(number))20 except Exception as e:21 raise e22 finally:23 lock.release()24 pass25 26 if __name__ == '__main__':27 print("start main")28 number = 029 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 mainend mainstart add1 number= 0number = 1number = 2number = 3number = 4start add3 number= 0number = 3number = 6number = 9number = 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 += value10 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 += value17 print("number = {0}".format(number.value))18 except Exception as e:19 raise e20 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 mainend mainstart add1 number= 0.0number = 1.0number = 2.0number = 3.0number = 4.0start add3 number= 4.0number = 7.0number = 10.0number = 13.0number = 16.0