Python Queue阻塞引发变量污染
大家先来看一段代码:
# -*- coding: utf-8 -*-
'''
Created on 2012-3-01
@author: rebill
'''
from multiprocessing import JoinableQueue, Process
import time
class C1(Process):
def __init__(self, queue):
Process.__init__(self)
self.queue = queue
def run(self):
for i in xrange(3):
data = {'a':i}
self.queue.put(data)
# time.sleep(0.1)
data['b'] = i
self.queue.put(data)
class C2(Process):
def __init__(self, queue):
Process.__init__(self)
self.queue = queue
def run(self):
while True:
item = self.queue.get()
if item != None:
print item
self.queue.task_done()
if __name__ == '__main__':
queue = JoinableQueue()
c1 = C1(queue)
c1.start()
c2 = C2(queue)
c2.start()
queue.join()
预期的结果应该是这样:
{'a': 0}
{'a': 0, 'b': 0}
{'a': 1}
{'a': 1, 'b': 1}
{'a': 2}
{'a': 2, 'b': 2}
但事实往往出乎你的意料,真正的输出应该是:
{'a': 0, 'b': 0}
{'a': 0, 'b': 0}
{'a': 1, 'b': 1}
{'a': 1, 'b': 1}
{'a': 2, 'b': 2}
{'a': 2, 'b': 2}
为什么会导致变量被污染了呢?
细心的你,应该看到我注释的代码
time.sleep(0.1)
没错,Python的Queue会阻塞,不过又不是全阻塞,它是半阻塞。就算你把queue.put换成queue.put_nowait(),结果还是一样的。但是在实际的生产环境中,你不可能加上time.sleep(0.1)这样的代码,解决的办法就是将两次put的变量名换成不一样的,防止变量被污染。
像这样:
data_a = {'a':i}
self.queue.put(data_a)
data_b = {'a':i, 'b':i}
self.queue.put(data_b)
或者你有什么其他更好的办法呢?欢迎一起探讨。


