我有一个队列,由两个多处理函数访问。这两个过程都使用队列中的同一项,然后将其清除。我希望每一个都只取一个唯一的值。我做错了什么?
import time
import queue
import multiprocessing
import threading
q = queue.Queue(maxsize=0)
run_1 = 1
run_2 = 1
def multi_one():
while run_1 == 1:
item = q.get()
q.task_done()
time.sleep(2)
print(item)
def multi_two():
while run_2 == 1:
item = q.get()
q.task_done()
time.sleep(2)
print(item)
p1 = multiprocessing.Process(target=multi_one)
p2 = multiprocessing.Process(target=multi_two)
for item in range(10):
q.put(item)
p1.start()
p2.start()
我得到的输出是:
0
0
1
1
2
2
...
我正在寻找的输出是:
0
1
2
3
4
5
6
7
8
9
您的代码包含几个错误,我将从文档中引用这些错误:
- 您应该使用if
__name__ == '__main__'
来保护程序的"入口点">
确保新的Python解释器可以安全地导入主模块,而不会产生意外的副作用(例如启动新进程(。
- 您应该将队列对象作为参数传递给构造函数
在使用fork-start方法的Unix上,子进程可以使用在使用全局资源的父进程中创建的共享资源。但是,最好将对象作为参数传递给子进程的构造函数。
- 如果要使用
JoinableQueue.task_done()
,则应使用multiprocessing.Queue
或multiprocessing.JoinableQueue
因为queue.Queue
仅在生产者和消费者都在同一进程中的多线程上下文中使用
考虑到以上注意事项,您的代码可以通过这种方式进行修改(尽管它还远远不够理想(:
import time
import multiprocessing
import threading
q = multiprocessing.JoinableQueue(maxsize=0)
run_1 = 1
run_2 = 1
def multi_one(q):
while run_1 == 1:
item = q.get()
q.task_done()
time.sleep(2)
print(item)
def multi_two(q):
while run_2 == 1:
item = q.get()
q.task_done()
time.sleep(2)
print(item)
if __name__ == "__main__":
p1 = multiprocessing.Process(target=multi_one, args=(q, ))
p2 = multiprocessing.Process(target=multi_two, args=(q, ))
for item in range(10):
q.put(item)
p1.start()
p2.start()
输出:
0
1
2
3
...
您使用了错误类型的Queue
,请尝试将其更改为multiprocessing.JoinableQueue
:
import time
import multiprocessing
q = multiprocessing.JoinableQueue(maxsize=0)
run_1 = 1
run_2 = 1
def multi_one(q):
while run_1 == 1:
item = q.get()
q.task_done()
time.sleep(2)
print(item)
def multi_two(q):
while run_2 == 1:
item = q.get()
q.task_done()
time.sleep(2)
print(item)
for item in range(10):
q.put(item)
p1 = multiprocessing.Process(target=multi_one, args=(q, ))
p2 = multiprocessing.Process(target=multi_two, args=(q, ))
p1.start()
p2.start()
打印:
0
1
2
3
4
5
6
7
8
9