我想在进程和线程之间共享一个列表。所以我找到了multiprocessing.Manager()
来创建列表。我写了下面这段代码:
import multiprocessing
import threading
import time
def consumer(l):
counter = 0
while counter < 20:
time.sleep(5)
l = l[len(l)/2:]
print "consumer l: {}".format(l)
counter += 5
def producer(l):
for i in range(10):
time.sleep(i)
l.append(i)
print "producer l: {}".format(l)
if __name__=="__main__":
mgr = multiprocessing.Manager()
l = mgr.list()
p = threading.Thread(target=producer, args=(l,))
c = multiprocessing.Process(target=consumer, args=(l,))
p.start()
c.start()
p.join()
c.join()
print "done"
它创建一个进程和一个共享由manager创建的列表的线程。生产者在每隔i秒后追加到列表,而消费者每隔5秒将列表减半。我预计这些列表将是相同的,并且两者都将在其上运行。但我观察到,消费者和制作人只共享一次列表,下次列表分开时。
观察到的输出:
producer l: [0]
producer l: [0, 1]
producer l: [0, 1, 2]
consumer l: [1, 2]
producer l: [0, 1, 2, 3]
producer l: [0, 1, 2, 3, 4]
consumer l: [2]
producer l: [0, 1, 2, 3, 4, 5]
consumer l: [2]
consumer l: [2]
producer l: [0, 1, 2, 3, 4, 5, 6]
producer l: [0, 1, 2, 3, 4, 5, 6, 7]
producer l: [0, 1, 2, 3, 4, 5, 6, 7, 8]
producer l: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
done
应该做些什么,以便他们两个都使用相同的列表?
答案 0 :(得分:0)
你的问题就在这一行:
l = l[len(l)/2:]
看起来没问题,但它实际上做的是创建l
的新副本并将l
分配给这个新对象。这意味着变量在您的第一个消费者执行时出现分歧,而消费者中的l
不再绑定到传递给它的l
。
考虑这个版本的消费者:
def consumer(l):
counter = 0
while counter < 20:
time.sleep(5)
n = len(l)/2
for _ in range(0,n+1):
try:
l.pop()
except IndexError:
pass
print "consumer l: {}".format(l)
counter += 5
它不是很优雅,它可能不是你想要的,但我已经用一个列表操作方法(在这种情况下为pop)替换为l
分配给新实例。只要您继续使用l
,pop
,append
或insert
等列表管理方法修改remove
,就可以了。
如果你将l
分配给新的东西,你的制作人会遇到同样的问题,但你已经有l.append()
,所以那部分没问题。
答案 1 :(得分:0)
我将程序更改为:
import multiprocessing
import threading
import time
def consumer(l):
counter = 0
while counter < 20:
time.sleep(5)
del l[0 : len(l)/2+1]
print("consumer l address {}".format(hex(id(l))))
print "consumer l: {}".format(l)
counter += 5
def producer(l):
for i in range(10):
time.sleep(i)
print("producer l address {}".format(hex(id(l))))
l.append(i)
print "producer l: {}".format(l)
if __name__=="__main__":
mgr = multiprocessing.Manager()
l = mgr.list()
print("list address {}".format(hex(id(l))))
p = multiprocessing.Process(target=producer, args=(l,))
c = multiprocessing.Process(target=consumer, args=(l,))
p.start()
c.start()
p.join()
c.join()
print "done"
请注意,我使用了del
而不是创建新列表并将其分配给旧列表。我还在上面的代码中添加了地址打印语句。如果按原样运行它,您应该看到列表的地址在任何地方都保持不变,因为我们没有重新创建列表。如果您将第9行更改回l = l[len(l)/2:]
并运行该程序,您应该注意到第一次操作后消费者和生产者的列表地址会发生变化。