同一进程线程之间可相互共用数据,子线程可访问主线程的队列,如下示例子线程p可访问主线程的q:
import threading
import queue #线程queue
from multiprocessing import Process,Queue #进程queue
def f(qq):
# q = queue.Queue()
qq.put([42,None,'hello'])
if __name__ == '__main__':
q = queue.Queue() #线程queue
p = threading.Thread(target=f,args=(q,))#开启一个子线程
p.start()
print(q.get())
[42, None, 'hello']
进程之间是相互独立的,不能相互访问。如要使进程之间通信,可使用队列Queue或Pipe管道化。
一、进程队列
进程不能访问线程队列。如下示例子进程p访问线程队列q时报错,错误信息为TypeError: can't pickle _thread.lock objects,因该线程队列没有序列化与反序列化后传给另一个进程
import threading
import queue #线程queue
from multiprocessing import Process,Queue #进程queue
def f(qq):
# q = queue.Queue()
qq.put([42,None,'hello'])
if __name__ == '__main__':
q = queue.Queue() #线程queue
# p = threading.Thread(target=f,args=(q,))
p = Process(target=f,args=(q,)) #启动一个子进程
p.start()
print(q.get())
TypeError: can't pickle _thread.lock objects
进程只能访问进程queue,如下子进程p可访问父进程队列q,实际上该子进程和父进程访问的不是同一个q,一个进程并不能直接访问另一个进程的内存。该父进程的q被pickle 序列化之后,再反序列化放到子进程内存,所以父进程和子进程内的是两个去,不是一个共享q。通过序列化将一个进程数据传递给另一个进程,但不是修改即子进程不能修改父进程的q,父进程也不能修改子进程的q。线程之间则不同,他们无需序列化就可共用一份数据,且可修改这同一分数据:
import threading
import queue #线程queue
from multiprocessing import Process,Queue #进程queue
def f(qq):
# q = queue.Queue()
qq.put([42,None,'hello'])
if __name__ == '__main__':
# q = queue.Queue() #线程queue
# p = threading.Thread(target=f,args=(q,))
q = Queue()
p = Process(target=f,args=(q,)) #启动一个子进程
p.start()
print(q.get())
[42, None, 'hello']
二、Pipe管道化
管道化就是连接了通信的两端:发送方和接收方,可相互通信如下示例:
from multiprocessing import Pipe,Process
def f(conn):
conn.send(['hello,father'])
print(conn.recv())
conn.close()
if __name__ == '__main__':
parent_conn,child_conn = Pipe()
print(parent_conn,child_conn)
p = Process(target=f,args=(child_conn,))
p.start()
print(parent_conn.recv())
parent_conn.send('hello,son')
p.join()
Pipe()会返回两个对象即发送方和接收方,管道化和Queue一样也只是实现了进程间数据的传递,并不是共享
进程之间共享递数据可用Manager,我们无需担心两个进程会不会同时修改一个数据造成数据错误,即无需我们考虑加锁处理该问题,Manager内部自己处理。我们加锁是为防止在屏幕上打印的时候出现混乱:
from multiprocessing import Manager,Process,Lock
import os
def f(dict1,list1):
dict1[1] = '1'
dict1['name'] = 'Tim'
dict1[0.3] = None
list1.append(os.getpid()) #拼接进程号
print('f list-->',list1)
if __name__ == '__main__':
lock = Lock()
manager = Manager()
d = manager.dict() #创建进程间共享和传递的字典
l = manager.list(range(5))#创建进程间共享和传递的列表
p_list = []
for i in range(5):
p = Process(target=f,args=(d,l))
p.start()
p_list.append(p)
for res in p_list: #等待所有进程执行完毕
res.join()
print('main dict:',d)
print('main list',l)
f list--> [0, 1, 2, 3, 4, 10404]
f list--> [0, 1, 2, 3, 4, 10404, 8332]
f list--> [0, 1, 2, 3, 4, 10404, 8332, 9892]
f list--> [0, 1, 2, 3, 4, 10404, 8332, 9892, 10720]
f list--> [0, 1, 2, 3, 4, 10404, 8332, 9892, 10720, 10688]
main dict: {0.3: None, 1: '1', 'name': 'Tim'}
main list [0, 1, 2, 3, 4, 10404, 8332, 9892, 10720, 10688]
网友评论