如果我以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 个不同实例。
谁能阐明这里幕后发生的事情?
我的解释正确吗?
您观察到这种行为是因为您一直在修改相同的对象
让我们把队列/线程放在一边,运行一个简化的代码,并有一些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.put() 线程安全?这意味着全局变量q可以安全地由多个并发线程访问。 答案是肯定的 - 它是线程安全的
队列模块实现多生产者、多使用者队列。它 在线程编程中特别有用,当信息必须 在多个线程之间安全地交换。此队列类 模块实现所有必需的锁定语义
在第一个示例中,您将相同的字典放入队列三次。这与队列无关。你会发现list.append也有同样的行为。