Проверяет знание механизмов взаимодействия между параллельными задачами.
Потоки используют общую память, но требуют блокировок (Lock), чтобы избежать гонки данных. Процессы не имеют общей памяти, поэтому обмениваются данными через Queue, Pipe или разделяемые объекты (Manager).
1. Для потоков (threading):
Общая память: Потоки одного процесса могут читать/писать в одни переменные.
Риск: Гонка данных (race condition), когда несколько потоков меняют данные одновременно.
Решение: Использовать Lock или RLock.
from threading import Thread, Lock
counter = 0
lock = Lock()
def increment():
global counter
with lock: # Блокируем доступ
counter += 1
threads = [Thread(target=increment) for _ in range(100)]
for t in threads: t.start()
for t in threads: t.join()
print(counter) # 1002. Для процессов (multiprocessing):
Очередь (Queue): Безопасный способ обмена данными.
from multiprocessing import Process, Queue
def worker(q):
q.put("Данные из процесса")
q = Queue()
p = Process(target=worker, args=(q,))
p.start()
print(q.get()) # "Данные из процесса"
p.join()Разделяемая память (Value, Array):
from multiprocessing import Process, Value
def increment(shared_val):
shared_val.value += 1
counter = Value("i", 0)
p = Process(target=increment, args=(counter,))
p.start()
p.join()
print(counter.value) # 1Менеджер (Manager): Создаёт объекты, доступные из разных процессов.
Вывод:
Для I/O-задач (сеть, файлы) используйте потоки с Lock.
Для CPU-задач — процессы с Queue/Manager.