- 进程的概念
进程是程序在计算机上的一次执行活动。
进程可分为系统进程和用户进程。
所有正在运行的进程轮流使用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