Ответ
В Python список (list
) не является потокобезопасным. Это означает, что если несколько потоков одновременно изменяют список (например, добавляют или удаляют элементы), это может привести к состоянию гонки (race condition), повреждению данных или неожиданному поведению. Это происходит потому, что операции со списком не являются атомарными.
Пример проблемы (состояние гонки):
import threading
shared_list = []
def add_items():
for i in range(1000):
shared_list.append(i)
threads = []
for _ in range(10):
t = threading.Thread(target=add_items)
threads.append(t)
t.start()
for t in threads:
t.join()
# Ожидаемый размер: 10 * 1000 = 10000
# Фактический размер может быть меньше из-за состояний гонки
print(len(shared_list))
Решение для потокобезопасной работы:
-
Использование
threading.Lock
: Это самый распространенный способ синхронизации доступа к общим ресурсам. Блокировка гарантирует, что только один поток может выполнять критическую секцию кода в любой момент времени.import threading lock = threading.Lock() shared_list = [] def add_items_safe(): for i in range(1000): with lock: # Захватываем блокировку перед изменением списка shared_list.append(i) threads = [] for _ in range(10): t = threading.Thread(target=add_items_safe) threads.append(t) t.start() for t in threads: t.join() print(len(shared_list)) # Будет 10000
-
Использование
queue.Queue
: Если требуется потокобезопасная структура данных с логикой FIFO (первым пришел — первым ушел),queue.Queue
из модуляqueue
является отличным выбором, так как он изначально разработан для потокобезопасного обмена данными между потоками. -
Для межпроцессного взаимодействия: Для обмена данными между процессами (не потоками) можно использовать
multiprocessing.Manager().list()
или другие средства синхронизации из модуляmultiprocessing
.