multiprocessing的用法、进程之间通信
记录multiprocessing的基本用法以及如何利用Queue进行进程间的通信
一个很简单的例子
from multiprocessing import Process
import multiprocessing as mp
# 每个进程要把y放入队列后,再放入一个'@'表示进程结束
def function_to_run(name, w, r):
y = w + 1
r.put(y)
r.put('@')
print('Hello', name, y)
if __name__ == '__main__':
rr = mp.Queue()
processes = []
scores = []
for i in range(5): # 创建5个进程
p = Process(target=function_to_run, args=(f'World {i}', i, rr)) # 创建一个进程对象
p.start() # 启动进程
processes.append(p) # 将进程对象添加到列表中
for p in processes: # 等待所有进程结束
p.join()
# 从队列取出之前放入的元素
# 注意:队列先存先取,取完即没
while not rr.empty(): # 如果队列不为空,则。。。
q = rr.get()
scores.append(q)
print("--------------- 主程序 ---------------")
print(scores)
输出为:
Hello World 0 1
Hello World 2 3
Hello World 3 4
HelloHello World 4 5
World 1 2
--------------- 主程序 ---------------
[1, '@', 3, '@', 4, '@', 5, 2, '@', '@']
你会发现,输出结果并不是我们想象的那样:数组中一个数字一个’@‘,这样排列。
这是因为这5个进程并行运行,结果存入队列rr
时,总的结果会由于进程先后存入。
比如:a进程向队列rr
存入2,马上要存’@'时,b进程向队列rr
存入1,这就导致显示为:[2, 1, '@']
。
利用get_lock()
锁对象可以用于同步进程,以避免多个进程同时访问或修改共享资源,从而可能导致数据不一致或其他并发问题。如果锁已经被另一个进程获取,那么这个进程就会被阻塞,直到锁被释放。
from multiprocessing import Process
import multiprocessing as mp
def function_to_run(name, w, e, r):
# w被某个进程锁定时,其他进程阻塞,等待
with w.get_lock():
y = w.value + e
r.put(y)
r.put('@')
print('Hello', name, y)
if __name__ == '__main__':
# 创建一个共享对象ww
ww = mp.Value('d', 0) # 'd' 表示浮点数类型
rr = mp.Queue()
rr.put('start')
processes = []
scores = []
for ee in range(5): # 创建5个进程
p = Process(target=function_to_run, args=(f'World {ee}', ww, ee, rr)) # 创建一个进程对象
p.start() # 启动进程
processes.append(p) # 将进程对象添加到列表中
for p in processes: # 等待所有进程结束
p.join()
while not rr.empty():
q = rr.get()
scores.append(q)
print(scores)
输出为:
Hello World 0 0.0
Hello World 1 1.0
Hello World 2 2.0
Hello World 4 4.0
Hello World 3 3.0
['start', 0.0, '@', 1.0, '@', 2.0, '@', 4.0, '@', 3.0, '@']
在主进程中谨慎使用 put()
运行以下程序:
import multiprocessing as mp
if __name__ == '__main__':
scores = []
sa = []
rr = mp.Queue()
rr.put('start')
rr.put(None)
rr.put('qq')
while not rr.empty():
q = rr.get()
scores.append(q)
print(scores)
while not rr.empty():
x = rr.get()
sa.append(x)
print(sa)
多运行几次你会发现:有以下几种情况。
['start', None, 'qq']
[]
或者
['start', None]
['qq']
或者
['start']
[None, 'qq']
或者
[]
['start', None, 'qq']