运行结果如下:
单线程处理结果: 999985000050000 单线程处理耗时: 0.10726284980773926 多线程处理结果: 999985000050000 多线程处理耗时: 0.13849401473999023 多进程处理结果: 999985000050000 多进程处理耗时: 0.041596174240112305
从上面的结果可以明显看出在处理CPU密集型任何时,多进程更优。
2.Value和Array
两者是通过「共享内存」的方式来共享数据的,前者用于需要共享单个值,后者用于
共享多个值(数组),构造函数的第一个元素为数据类型,第二个元素为值。数据类型对照如表所示。
标记 | 数据类型 | 标记 | 数据类型 |
'c' | ctypes.c_char | 'u' | ctypes.c_wchar |
'b' | ctypes.c_byte | 'B' | ctypes.c_ubyte |
'h' | ctypes.c_short | 'H' | ctypes.c_ushort |
'i' | ctypes.c_int | 'I' | ctypes.c_uint |
'l' | ctypes.c_long | 'L' | ctypes.c_ulong |
'f' | ctypes.c_float | 'd' | ctypes.c_double |
使用代码示例如下:
import multiprocessing as mp def do_something(num, arr): num.value += 1 for i in range(len(arr)): arr[i] = arr[i] * 2 if __name__ == '__main__': value = mp.Value('i', 1) array = mp.Array('i', range(5)) print("刚开始的值:", value.value, array[:]) # 创建进程1 p1 = mp.Process(target=do_something, args=(value, array)) p1.start() p1.join() print("进程1操作后的值:", value.value, array[:]) # 创建进程2 p2 = mp.Process(target=do_something, args=(value, array)) p2.start() p2.join() print("进程2操作后的值:", value.value, array[:])
运行结果如下:
刚开始的值: 1 [0, 1, 2, 3, 4] 进程1操作后的值: 2 [0, 2, 4, 6, 8] 进程2操作后的值: 3 [0, 4, 8, 12, 16]
3.Manager
Python还为我们提供更加强大的数据共享类,支持更丰富的数据类型,比如Value、Array、dict、list、Lock、Semaphore等等,另外Manager还可以共享类的实例对象。有一点要注意:进程间通信应该尽量避免使用共享数据的方式!
使用代码示例如下:
import multiprocessing as mp import os import time def do_something(dt): dt[os.getpid()] = int(time.time()) print(data_dict) if __name__ == '__main__': manager = mp.Manager() data_dict = manager.dict() for i in range(3): p=mp.Process(target=do_something,args=(data_dict,)) p.start() p.join()
运行结果如下:
{5432: 1533200189} {5432: 1533200189, 5433: 1533200189} {5432: 1533200189, 5433: 1533200189, 5434: 1533200189}
4.Pipe
管道,简化版的Queue,通过Pipe()构造函数可以创建一个进程通信用的管道对象,默认双向,意味着使用管道只能同时开启两个进程!如果想设置单向,可以添加参数「duplex=False」,双向即可发送也可接受,但是只允许前面的端口用于接收,后面的端口用于发送。管道对象发送和接收信息的函数依次为send()和recv()。使用代码示例如下:
import multiprocessing as mp def p_1(p): p.send("你好啊!") print("P1-收到信息:", p.recv()) def p_2(p): print("P2-收到信息:", p.recv()) p.send("你也好啊!") if __name__ == '__main__': pipe = mp.Pipe() p1 = mp.Process(target=p_1, args=(pipe[0],)) p2 = mp.Process(target=p_2, args=(pipe[1],)) p1.start() p2.start() p1.join() p2.join()
运行结果如下:
P2-收到信息: 你好啊! P1-收到信息: 你也好啊!
关于多进程加锁的,可以参见前面多进程加锁部分内容,这里就不重复讲解了,只是导包换成了multiprocessing,比如threading.Lock换成了multiprocessing.Lock。