并发编程时,通常尽量避免使用共享状态,但如果有一些数据确实需要在进程之间共享怎么办呢?对于这种情况,multiprocessing 模块提供了两种方式。
共享内存
multiprocessing.Value(typecode_or_type, *args, lock=True)
返回一个从共享内存上创建的对象。参数说明如下:
- typecode_or_type:返回的对象类型。
- *args:传给类的构造函数。
- lock:如果 lock 值是 True(默认值),将会新建一个递归锁用于同步此值的访问操作;如果 lock 值是 Lock、RLock 对象,那么这个传入的锁将会用于同步这个值的访问操作;如果 lock 是 False,那么对这个对象的访问将没有锁保护,也就是说这个变量不是进程安全的。
multiprocessing.Array(typecode_or_type, size_or_initializer, *, lock=True)
从共享内存中申请并返回一个数组对象。
- typecode_or_type:返回的数组中的元素类型。
- size_or_initializer:如果参数值是一个整数,则会当做数组的长度;否则参数会被当成一个序列用于初始化数组中的每一个元素,并且会根据元素个数自动判断数组的长度。
- lock:说明同上。
使用 Value 或 Array 将数据存储在共享内存映射中。
from multiprocessing import Process, Value, Array def setData(n, a): n.value = 1024 for i in range(len(a)): a[i] = -a[i] def printData(n, a): print(num.value) print(arr[:]) if __name__ == '__main__': num = Value('d', 0.0) arr = Array('i', range(5)) print(num.value) print(arr[:]) print('-----------------------') p = Process(target=setData, args=(num, arr)) p.start() p.join() print(num.value) print(arr[:])
服务进程
由 Manager() 返回的管理器对象控制一个服务进程,该进程保存 Python 对象并允许其他进程使用代理操作它们。 Manager() 返回的管理器支持类型包括:list、dict、Namespace、Lock、RLock、Semaphore、BoundedSemaphore、Condition、Event、Barrier、Queue、Value 和 Array。
from multiprocessing import Process, Manager def setData(d, l): d[1] = '1' d[0.5] = None l.reverse() if __name__ == '__main__': with Manager() as manager: d = manager.dict() l = manager.list(range(5)) print(d) print(l) print('-----------------------') p = Process(target=setData, args=(d, l)) p.start() p.join() print(d) print(l)