Синхронизация процессов с помощью multiprocessing.Lock() позволяет предотвратить состояние гонки (race condition) и обеспечить безопасный доступ к общим ресурсам (например, файлам, переменным) из нескольких процессов.  Lock предоставляет базовый механизм взаимоисключения, гарантируя, что только один процесс в данный момент времени может владеть этим блокировщиком.
Вот как это работает:
Lock. Это делается обычно в главной программе, до запуска дочерних процессов.lock.acquire(). Если блокировщик свободен, процесс захватывает его и продолжает выполнение. Если блокировщик уже занят другим процессом, вызывающий процесс блокируется до тех пор, пока блокировщик не будет освобожден.lock.release(). Это позволяет другому ожидающему процессу захватить блокировщик и получить доступ к ресурсу.Рекомендуется использовать блокировку в блоке try...finally, чтобы гарантировать, что блокировщик будет освобожден даже в случае возникновения исключения.
Пример:
import multiprocessing
import time
def worker(lock, shared_resource):
    lock.acquire()  # Захватываем блокировщик
    try:
        print(f"Процесс {multiprocessing.current_process().name} начал работу.")
        # Критическая секция - безопасный доступ к общему ресурсу
        shared_resource.value += 1
        time.sleep(1) # Имитация работы с ресурсом
        print(f"Процесс {multiprocessing.current_process().name} увеличил shared_resource до {shared_resource.value}")
    finally:
        lock.release()  # Освобождаем блокировщик (обязательно!)
        print(f"Процесс {multiprocessing.current_process().name} завершил работу.")
if __name__ == '__main__':
    lock = multiprocessing.Lock()
    shared_resource = multiprocessing.Value('i', 0)  # 'i' означает integer
    processes = []
    for i in range(3):
        p = multiprocessing.Process(target=worker, args=(lock, shared_resource), name=f"Process-{i+1}")
        processes.append(p)
        p.start()
    for p in processes:
        p.join()
    print(f"Финальное значение shared_resource: {shared_resource.value}")
В этом примере, shared_resource - это общая переменная, а lock - это блокировщик.  Каждый процесс пытается увеличить значение shared_resource на 1. Без блокировки,  несколько процессов могли бы одновременно прочитать значение shared_resource, увеличить его и записать обратно, что привело бы к неправильному конечному значению.  Блокировщик гарантирует, что только один процесс одновременно имеет доступ к критической секции кода, где изменяется shared_resource,  таким образом избегая состояния гонки.
Альтернативой использованию lock.acquire() и lock.release() является использование контекстного менеджера with lock:, который автоматически захватывает и освобождает блокировщик, что делает код чище и предотвращает забывание освобождения блокировщика:
def worker_with_context_manager(lock, shared_resource):
    with lock:  # Автоматически захватывает и освобождает блокировщик
        print(f"Процесс {multiprocessing.current_process().name} начал работу.")
        shared_resource.value += 1
        time.sleep(1)
        print(f"Процесс {multiprocessing.current_process().name} увеличил shared_resource до {shared_resource.value}")
        print(f"Процесс {multiprocessing.current_process().name} завершил работу.")