Я хотел бы знать, являются ли встроенные контейнеры Python (список, вектор, набор ...) потокобезопасными? Или мне нужно реализовать среду блокировки/разблокировки для моей общей переменной?Являются ли встроенные контейнеры Python в потоковом режиме?
ответ
Вам необходимо реализовать свою собственную блокировку для всех общих переменных, которые будут изменены в Python. Вам не нужно беспокоиться о чтении из переменных, которые не будут изменены (т. Е. Одновременные чтения в порядке), поэтому неизменяемые типы (frozenset
, tuple
, str
) являются , вероятно, безопасными, но это не помешает. Для вещей, которые вы собираетесь менять - list
, set
, dict
, и большинство других объектов, у вас должен быть свой собственный механизм блокировки (в то время как операции на месте в порядке на большинстве из них, потоки могут привести к супер-неприятным ошибкам - вы можете также реализовать блокировку, это довольно легко).
Кстати, я не знаю, если вы знаете это, но замок очень легко в Python - создать объект threading.lock, а затем вы можете приобрести/снять его так:
import threading
list1Lock = threading.Lock()
with list1Lock:
# change or read from the list here
# continue doing other stuff (the lock is released when you leave the with block)
В Python 2.5, do from __future__ import with_statement
; Python 2.4 и до этого нет, так что вы хотите поставить приобретаемой()/Release() вызывает в try:...finally:
блоков:
import threading
list1Lock = threading.Lock()
try:
list1Lock.acquire()
# change or read from the list here
finally:
list1Lock.release()
# continue doing other stuff (the lock is released when you leave the with block)
Some very good information about thread synchronization in Python.
Они потокобезопасны, если вы не отключите GIL в коде C для потока.
Это деталь реализации CPython, на которую вы не должны включать реле. Вероятно, это произойдет в будущем, а другие реализации этого не будут иметь. –
Георг - этот аспект python меня интересует. Не обращайте внимания на все ошибки, которые выпадают из java-программ, когда 8 ядер становятся обычными на рабочем столе. Что происходит, когда GIL удаляется, и многопоточные приложения python неожиданно работают на 8 ящиках? – Ben
Не должно никого напугать, если они не притворяются, что их код является потокобезопасным, когда это явно не так. :) – Kylotan
Да, но вы все равно должны быть осторожны, конечно
Например:
Если две нити мчитесь pop()
из списка только один пункт, один поток будет получить деталь успешно и другие получат IndexError
код, как это не поточно-
if L:
item=L.pop() # L might be empty by the time this line gets executed
Вы должны Wr ite это как это
try:
item=L.pop()
except IndexError:
# No items left
Я хочу, чтобы pop() был потокобезопасным, но я не могу найти этот факт в документации. Может кто-нибудь помочь мне исправить это требование, прежде чем я возьму его как Евангелие? –
Действительно? list.pop() не является потокобезопасным? Я видел еще одну статью, утверждающую обратное. http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm –
@ Zhongjun'Mark'Jin он сказал, что это потокобезопасно .. но это не значит вам не нужно учитывать другие потоки. Если один поток выталкивает последний элемент, а затем пытается использовать другой поток, он получит IndexError, как он говорит. – fantabolous
Я считаю, что для тех, кто раньше не использовал блокировки потоков, следует отметить, что блокировка (в вашем примере, 'list1Lock') должна быть * совместно используемой * между потоками, чтобы она работала правильно. Два независимых замка, по одному для каждой нити, ничего не запирали, просто добавляли глупые накладные расходы. – tzot
Не должно быть: со списком1Lock: # Сделайте что-нибудь –
@ slack3r Хороший звонок! –