python 的 queue.Queue.put() 方法是异步的吗?

Is python's queue.Queue.put() method asynchronous?

如果我运行一个具有以下功能的线程作为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() 方法 运行s 在 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 个不同实例。

任何人都可以阐明幕后发生的事情吗?

在第一个示例中,您将同一个字典放入队列中三次。这与队列无关。您会发现 list.append 有相同的行为。

我的理解对吗?

您观察到这种行为是因为您一直在修改同一个对象

让我们抛开队列/线程和 运行 一个简化的等效代码,其中包含一些 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]

所以这与我们无关 threads/queues - 您只是将同一个对象添加了 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 - 它是线程安全的

The Queue module implements multi-producer, multi-consumer queues. It is especially useful in threaded programming when information must be exchanged safely between multiple threads. The Queue class in this module implements all the required locking semantics