正如您从标题中所知,我尝试将PriorityQueue与多处理结合使用。更确切地说,我想制作共享的PriorityQueue,编写一些代码并且它没有像我预期的那样运行。
查看代码:
import time
from multiprocessing import Process, Lock
from Queue import PriorityQueue
def worker(queue):
lock = Lock()
with lock:
for i in range(100):
queue.put(i)
print "worker", queue.qsize()
pr_queue = PriorityQueue()
worker_process = Process(target = worker, args = (pr_queue,))
worker_process.start()
time.sleep(5) # nope, race condition, you shall not pass (probably)
print "main", pr_queue.qsize()
得到以下输出:
worker 100
main 0
发生了什么以及如何以正确的方式做我想要的事情? 谢谢。
答案 0 :(得分:11)
问题不是在这种情况下它不可挑选 - 如果你使用类似Unix的平台,队列可以传递给孩子而不进行酸洗。 (在Windows上,我认为你会在这里遇到酸洗错误)。根本问题是您没有使用进程安全队列。进程之间可以使用的唯一队列是the Queue
objects,它们位于multiprocessing
模块中。遗憾的是,没有PriorityQueue
实施可用。但是,您可以通过注册PriorityQueue
和multiprocessing.Manager
类轻松创建一个,如下所示:
import time
from multiprocessing import Process
from multiprocessing.managers import SyncManager
from Queue import PriorityQueue
class MyManager(SyncManager):
pass
MyManager.register("PriorityQueue", PriorityQueue) # Register a shared PriorityQueue
def Manager():
m = MyManager()
m.start()
return m
def worker(queue):
print(queue)
for i in range(100):
queue.put(i)
print "worker", queue.qsize()
m = Manager()
pr_queue = m.PriorityQueue() # This is process-safe
worker_process = Process(target = worker, args = (pr_queue,))
worker_process.start()
time.sleep(5) # nope, race condition, you shall not pass (probably)
print "main", pr_queue.qsize()
输出:
worker 100
main 100
请注意,这可能不会像标准multiprocessing.Queue
子类那样表现得那么好。基于Manager
的{{1}}是通过创建PriorityQueue
服务器进程实现的,该进程实际上包含常规Manager
,然后为您的主进程和工作进程提供Proxy
在服务器进程中使用IPC读取/写入队列的对象。常规PriorityQueue
只是向/ multiprocessing.Queue
写入/读取数据。如果这是一个问题,您可以尝试通过从Pipe
继承或委派来实现自己的multiprocessing.PriorityQueue
。但是,这可能不值得。