????? 標(biāo)準(zhǔn)庫 multiprocessing 支持使用類似于 threading 的用法來創(chuàng)建管理線程,并且避免了 GIL 問題。
13.4.1 創(chuàng)建線程
from multiprocessing import Process
import os
def f(name):
print('module name:', __name__)
print('parent process:', os.getppid())
print('process id:', os.getpid())
print('hello', name)
if __name__ == '__main__':
p = Process(target = f, args = ('bob',))
p.start()
p.join()
????? multiprocessing 還提供了 Pool 對象支持?jǐn)?shù)據(jù)的并行操作。下面的代碼并發(fā)計算二維數(shù)組每行的平均值。
from multiprocessing import Pool
from statistics import mean
def f(x):
return mean(x)
if __name__ == '__main__':
x = [list(range(10)), list(range(20, 30)), list(range(50, 60)), list(range(80, 90))]
with Pool(5) as p:
print(p.map(f, x))
13.4.2 進(jìn)程間數(shù)據(jù)交換
????? 使用 Queue 對象在進(jìn)程間交換數(shù)據(jù)。
import multiprocessing as mp
def foo(q):
q.put('hello world!')
if __name__ == '__main__':
mp.set_start_method('spawn')
q = mp.Queue()
p = mp.Process(target = foo, args = (q,))
p.start()
p.join()
print(q.get())
????? 也可以使用上下文對象 context 的 Queue 對象實(shí)現(xiàn)進(jìn)程間的數(shù)據(jù)交換。
import multiprocessing as mp
def foo(q):
q.put('hello world')
if __name__ == '__main__':
ctx = mp.get_context('spawn')
q = ctx.Queue()
p = ctx.Process(target = foo, args = (q,))
p.start()
p.join()
print(q.get())
????? 使用管道實(shí)現(xiàn)數(shù)據(jù)交換。
from multiprocessing import Process, Pipe
def f(conn):
conn.send('hello world') # 向管道中發(fā)送數(shù)據(jù)
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe() # 創(chuàng)建管道對象
p = Process(target = f, args = (child_conn,)) # 將管道的一方作為參數(shù)傳遞給子進(jìn)程
p.start()
print(parent_conn.recv()) # 通過管道的另一方接收數(shù)據(jù)
p.join()
????? 使用共享內(nèi)存實(shí)現(xiàn)進(jìn)程間數(shù)據(jù)交換。
from multiprocessing import Process, Value, Array
def f(n, a):
n.value = 3.1415927
for i in range(len(a)):
a[i] = a[i] * a[i]
if __name__ == '__main__':
num = Value('d', 0.0) # 實(shí)型
arr = Array('i', range(10)) # 整數(shù)型
p = Process(target = f, args = (num, arr))
p.start()
p.join()
print(num.value)
print(arr[:])
????? 使用Manager 對象實(shí)現(xiàn)進(jìn)程間數(shù)據(jù)交換。
????? Manager 對象控制一個擁有 list、dict、Lock、RLock、Semaphore、BoundeSemaphore、Condition、Event、Barrier、Queue、Value、Array、Namespace 等對象的服務(wù)端進(jìn)程,允許其他進(jìn)程訪問這些對象。
from multiprocessing import Process, Manager
def f(d, l, t):
d['name'] = 'dfg'
d['age'] = 38
d['sex'] = 'Male'
d['affiliation'] = 'SDIBT'
l.reverse()
t.value = 3
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
l = manager.list(range(10))
t = manager.Value('i', 0)
p = Process(target = f, args = (d, l, t))
p.start()
p.join()
for item in d.items():
print(item)
print(l)
print(t.value)
13.4.3 進(jìn)程同步
????? 使用 Lock 對象實(shí)現(xiàn)進(jìn)程同步。
from multiprocessing import Process, Lock
def f(l, i):
l.acquire()
try:
print('hello world', i)
finally:
l.release()
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target = f, args = (lock, num)).start()
????? 使用 Event 對象實(shí)現(xiàn)進(jìn)程同步。
from multiprocessing import Process, Event
def f(e, i):
if e.is_set():
e.wait()
print('hello world', i)
e.clear()
else :
e.set()
if __name__ == '__main__':
e = Event()
for num in range(10):
Process(target = f, args = (e, num)).start()