Вопрос проверяет понимание механизма блокировок (Lock) для синхронизации потоков и предотвращения состояния гонки при работе с общими ресурсами.
Lock (часто называемый мьютексом) — это базовый механизм синхронизации в многопоточном программировании. Его основная цель — обеспечить эксклюзивный доступ к общему ресурсу (например, переменной, файлу, структуре данных) для одного потока в определённый момент времени. Это предотвращает состояние гонки (race condition), когда несколько потоков одновременно читают и изменяют данные, приводя к непредсказуемым и ошибочным результатам.
Lock имеет два основных состояния: "заблокирован" (locked) и "разблокирован" (unlocked). Когда поток хочет войти в критическую секцию (участок кода, работающий с общим ресурсом), он пытается захватить блокировку. Если блокировка свободна, поток захватывает её и продолжает выполнение. Если же блокировка уже захвачена другим потоком, текущий поток блокируется (переходит в состояние ожидания) до тех пор, пока блокировка не будет освобождена.
Рассмотрим классический пример с увеличением счётчика из нескольких потоков без блокировки и с её использованием.
import threading
# Общий ресурс
counter = 0
# Функция без защиты
def increment_without_lock():
global counter
for _ in range(100000):
counter += 1 # Это не атомарная операция!
# Функция с защитой Lock
lock = threading.Lock()
def increment_with_lock():
global counter
for _ in range(100000):
lock.acquire() # Захватываем блокировку
try:
counter += 1
finally:
lock.release() # Всегда освобождаем
# Создаём потоки
threads = []
for _ in range(10):
t = threading.Thread(target=increment_with_lock)
threads.append(t)
t.start()
# Ждём завершения всех потоков
for t in threads:
t.join()
print(f"Final counter: {counter}") # Будет 1000000 только с LockВывод: Lock — фундаментальный инструмент для безопасной работы с общими ресурсами в многопоточной среде. Его стоит применять всегда, когда несколько потоков могут одновременно изменять одни и те же данные. Однако важно использовать блокировки аккуратно, чтобы избежать взаимных блокировок и не снизить производительность.