Общесистемный мьютекс в Python на Linux - PullRequest
50 голосов
/ 03 августа 2011

Есть ли какой-нибудь простой способ иметь общесистемный мьютекс в Python в Linux? Под «общесистемной» я подразумеваю, что мьютекс будет использоваться группой процессов Python ; это в отличие от традиционного мьютекса, который используется группой потоков в одном и том же процессе.

РЕДАКТИРОВАТЬ: Я не уверен, что пакет Python multiprocessing это то, что мне нужно. Например, я могу выполнить следующее в двух разных интерпретаторах:

from multiprocessing import Lock
L = Lock()
L.acquire()

Когда я выполняю эти команды одновременно в двух разных интерпретаторах, я хочу, чтобы один из них завис. Вместо этого ни один не висит; похоже, они не получают тот же мьютекс.

Ответы [ 4 ]

28 голосов
/ 27 февраля 2012

«Традиционный» ответ Unix - использовать блокировки файлов. Вы можете использовать lockf(3) для блокировки разделов файла, чтобы другие процессы не могли его редактировать; очень распространенным злоупотреблением является использование этого в качестве взаимного исключения между процессами. Эквивалент Python - fcntl.lockf .

Традиционно вы записываете PID процесса блокировки в файл блокировки, так что взаимные блокировки из-за процессов, умирающих при удержании блокировки, можно идентифицировать и исправить.

Это дает вам то, что вы хотите, поскольку ваша блокировка находится в глобальном пространстве имен (файловой системе) и доступна для всех процессов. Этот подход также имеет преимущество в том, что не-Python-программы могут участвовать в вашей блокировке. Недостатком является то, что вам нужно место для этого файла блокировки, чтобы жить; Кроме того, некоторые файловые системы на самом деле не блокируются правильно, поэтому существует риск, что они молча не смогут добиться исключения. Вы выиграли, некоторые проиграли.

12 голосов
/ 03 августа 2011

Стандарт POSIX определяет межпроцессные семафоры, которые могут использоваться для этой цели. http://linux.die.net/man/7/sem_overview

Модуль multiprocessing в Python построен на этом API и других. В частности, multiprocessing.Lock обеспечивает перекрестный процесс "мьютекс". http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

РЕДАКТИРОВАТЬ , чтобы ответить на отредактированный вопрос:

В вашем доказательстве концепции каждый процесс создает Lock(). Итак, у вас есть два отдельных замка. Вот почему ни один процесс не ждет. Вам нужно будет использовать одну и ту же блокировку для процессов Раздел, на который я ссылался в документации multiprocessing, объясняет, как это сделать.

8 голосов
/ 08 марта 2018

Попробуйте ilock библиотека:

from ilock import ILock

with ILock('Unique lock name'):
    # The code should be run as a system-wide single instance
    ...
1 голос
/ 19 мая 2016

Для общесистемного мьютекса, который обеспечивает синхронизацию абсолютно отдельных процессов (т. Е. Для включения процессов Linux, которые НЕ принадлежат одному и тому же дереву процессов), просто используйте fcntl.flock .Я предполагаю, что использование файла памяти в папке Linux '/ run / shm может заставить его работать быстрее.

Подробнее здесь .

...