Приведи пример атомарной операции в Python.

Ответ

Атомарная операция — это операция, которая выполняется как единое целое, без возможности прерывания или вмешательства других потоков/процессов. Либо она выполняется полностью, либо не выполняется вовсе.

В Python, из-за Global Interpreter Lock (GIL), некоторые операции, которые кажутся атомарными (например, присваивание ссылки на объект), на самом деле являются таковыми на уровне байт-кода. Однако составные операции, такие как counter += 1 (которая состоит из чтения значения, инкремента и записи нового значения), не являются атомарными и могут привести к некорректным результатам в многопоточной среде без синхронизации.

Для обеспечения атомарности составных операций в Python используются механизмы синхронизации, такие как блокировки (locks).

Пример атомарной операции с использованием threading.Lock:

В этом примере мы хотим безопасно инкрементировать счетчик из нескольких потоков. Операция counter += 1 сама по себе не атомарна, но мы делаем ее атомарной, обернув в блок, защищенный threading.Lock.

import threading

counter = 0
lock = threading.Lock() # Создаем объект блокировки

def increment_counter():
    """Функция для инкремента счетчика в потоке."""
    global counter
    with lock: # Захватываем блокировку перед доступом к общему ресурсу
        # Этот блок кода выполняется атомарно:
        # Ни один другой поток не сможет войти в этот блок,
        # пока текущий поток не выйдет из него.
        counter += 1
    # Блокировка автоматически освобождается при выходе из 'with' блока

# Создаем и запускаем несколько потоков
threads = []
for _ in range(1000): # Например, 1000 инкрементов
    t = threading.Thread(target=increment_counter)
    threads.append(t)
    t.start()

# Ожидаем завершения всех потоков
for t in threads:
    t.join()

print(f"Финальное значение счетчика: {counter}") # Гарантированно выведет 1000

Без использования lock, финальное значение counter было бы непредсказуемым и, скорее всего, меньше 1000 из-за гонок данных. Блокировка гарантирует, что операция чтения, инкремента и записи для counter выполняется как единое целое, предотвращая одновременный доступ и обеспечивая корректный результат.