Является ли метод python queue.Queue.put() асинхронным?
Если я запускаю поток со следующей функцией в качестве рабочего,
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 различным экземплярам словаря со своими собственными парами ключ-значение.
Может кто-нибудь пролить свет на то, что здесь происходит за занавесом?
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 может быть безопасно доступна нескольким параллельным потокам. Ответ - да, это потокобезопасный
Модуль Queue реализует многопользовательские, многопользовательские очереди. Это особенно полезно в многопоточном программировании, когда необходимо безопасно обмениваться информацией между несколькими потоками. Класс Queue в этом модуле реализует всю необходимую семантику блокировки
В первом примере вы помещаете один и тот же дикт в очередь три раза. Это не имеет ничего общего с очередью. Вы найдете то же поведение с list.append.