python的queue.Queue.put()方法是异步的吗? [复制]
Posted
技术标签:
【中文标题】python的queue.Queue.put()方法是异步的吗? [复制]【英文标题】:Is python's queue.Queue.put() method asynchronous? [duplicate] 【发布时间】:2018-07-18 16:52:14 【问题描述】:如果我作为worker运行具有以下函数的线程,
q = queue.Queue()
def worker():
while True:
t =
for i in range(3):
t['a'] = i
q.put(t)
队列中填充了完全相同的字典,即'a': 2
,而不是序列'a': 0, 'a': 1, 'a': 2
。我认为这是因为 put()
方法在 for 循环完成后运行,i
的最后一个值为 2。我的解释正确吗?
现在,如果我在 for 循环中移动字典的实例化,
def worker():
while True:
for i in range(3):
t = 'a': i
q.put(t)
队列中填充了所需的序列。我的解释是,首先,我在内存中创建一个字典对象,然后开始一个 for 循环并重新分配其值 3 次,但 put()
调用发生在循环完成后。在第二个实例中,我在 for 循环的每次迭代中创建一个新的字典对象,因此当循环之后发生 put()
调用时,它们会使用自己的键值对访问字典的 3 个不同实例。
谁能解释一下幕后发生的事情?
【问题讨论】:
不,Queue.put 不是异步的。您只是一遍又一遍地添加相同的字典。您没有创建副本。查看副本。 【参考方案1】:在第一个示例中,您将相同的 dict 放入队列 3 次。这与队列无关。您会发现与 list.append 相同的行为。
【讨论】:
但是put()
在字典修改后立即在 for 循环中被调用。修改后的字典不应该放到队列中吗?
哦,我明白你的意思了。对同一对象的三个引用被放置在队列中,并且该对象在循环之后具有最终状态,即'a'=2。【参考方案2】:
我的解释对吗?
您观察到这种行为是因为您一直在修改同一个对象
让我们把队列/线程放在一边,用一些prints
运行代码的简化等效项,以了解发生了什么
t =
l = []
for i in range(3):
t['a'] = i
l.append(t)
print(l)
t['a'] = 20
print(l)
print(map(id, l))
['a': 2, 'a': 2, 'a': 2]
['a': 20, 'a': 20, 'a': 20]
# they are all the same!
[4474861840, 4474861840, 4474861840]
所以它与我们线程/队列无关 - 你只是添加相同的对象 3 次。
现在,如果我将字典的实例化移动到 for 循环中
在这种情况下,您每次都创建一个新对象,如下代码所示:
l = []
for i in range(3):
t =
t['a'] = i
l.append(t)
print(l)
t['a'] = 20
print(l)
print(map(id, l))
['a': 0, 'a': 1, 'a': 2]
['a': 0, 'a': 1, 'a': 20]
# they are all different!
[4533475600, 4533502592, 4533502872]
所以这里没有魔法
回到你的问题
您可能会感兴趣:“python 的 queue.Queue.put() 线程安全吗?”意味着可以访问全局变量 q通过多个并发线程安全。 答案是yes - 它是线程安全的
Queue 模块实现了多生产者、多消费者队列。它 在线程编程中特别有用,当信息必须是 在多个线程之间安全地交换。这个队列类 模块实现了所有需要的锁定语义
【讨论】:
以上是关于python的queue.Queue.put()方法是异步的吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章