Являются ли Python встроенными контейнерами потокобезопасными?

Я хотел бы знать, являются ли встроенные контейнеры Python (список, вектор, набор...) потокобезопасными? Или мне нужно реализовать среду блокировки/разблокировки для моей общей переменной?

Ответ 1

Вам нужно реализовать свою собственную блокировку для всех общих переменных, которые будут изменены в 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 выполните from __future__ import with_statement; Python 2.4 и до этого не имеют этого, поэтому вы хотите поместить вызовы purchase()/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)

Некоторая очень хорошая информация о синхронизации потоков в Python.

Ответ 2

Да, но вам все равно нужно быть осторожным.

Например:

Если два потока участвуют в pop() из списка только с одним элементом, один поток получит элемент успешно, а другой получит IndexError

Код, подобный этому, не является потокобезопасным

if L:
    item=L.pop() # L might be empty by the time this line gets executed

Вы должны написать так:

try:
    item=L.pop()
except IndexError:
    # No items left

Ответ 3

Они потокобезопасны, если вы не отключите GIL в коде C для потока.