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

标签 multithreading python-3.x queue late-binding

<分区>

如果我作为 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 个不同实例 -值对。

谁能阐明幕后发生的事情?

最佳答案

我的解释对吗?

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

让我们抛开队列/线程并运行一个简化的等效代码,其中包含一些打印以了解正在发生的事情

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 - 它是线程安全的

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

关于multithreading - python的queue.Queue.put()方法是异步的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48680064/

相关文章:

android - 中断 HttpURLConnection 请求 Android

Python:如何在 Selenium 中隐藏输出的 Chrome 消息?

While 循环中的 Python 随机数

Python多处理,代码继续执行?

data-structures - 队列操作/API 的术语/命名约定?

c# - 使用C#的多线程实践和方法

c - cond.signal 或 lock.release 有问题吗?

c# - ProgressBar 从另一个线程更新

python - 遍历和提取​​树的节点时出现问题?

php - Laravel 队列推送监听器——队列监控