Linux上Python系统范围的互斥体

emc*_*sen 51 python linux mutex

有没有简单的方法在Linux上使用Python系统范围的互斥?通过"系统范围",我的意思是互斥体将被一组Python 进程使用 ; 这与传统互斥体形成对比,传统互斥体由同一进程中的一组线程使用.

编辑:我不确定Python的multiprocessing包是我需要的.例如,我可以在两个不同的解释器中执行以下操作:

from multiprocessing import Lock
L = Lock()
L.acquire()
Run Code Online (Sandbox Code Playgroud)

当我在两个单独的解释器中同时执行这些命令时,我希望其中一个挂起.相反,它们都没有挂起; 看起来他们没有获得相同的互斥锁.

zmc*_*ord 30

"传统的"Unix答案是使用文件锁.您可以使用lockf(3)锁定文件的各个部分,以便其他进程无法编辑它; 一个非常常见的滥用是将其用作进程之间的互斥.python等价物是fcntl.lockf.

传统上,您将锁定进程的PID写入锁定文件,以便在保持锁定时由于进程死亡而导致的死锁是可识别和可修复的.

这可以获得您想要的,因为您的锁在全局命名空间(文件系统)中并且可供所有进程访问.这种方法还具有非Python程序可以参与锁定的特权.缺点是你需要一个这个锁文件存放的地方; 此外,某些文件系统实际上并未正确锁定,因此存在无法实现排除的风险.你赢了一些,你输了一些.

  • http://blog.vmfarms.com/2011/03/cross-process-locking-and.html有一个示例实现(使用flock); 在Solaris上运行良好 (3认同)
  • 锁定文件的逻辑位置是“/var/lock” - 但是,如果将有大量锁定操作,我建议“/tmp”,因为并非所有系统在“tmpfs” ramdisk 中都有“/var/lock” 。 (2认同)
  • 哪些文件系统无法正确锁定?或者,我在哪里可以找到有关哪些文件系统未正确锁定的信息? (2认同)

wbe*_*rry 12

POSIX标准指定了可用于此目的的进程间信号量. http://linux.die.net/man/7/sem_overview

multiprocessingPython中的模块是基于此API和其他模块构建的.特别是,multiprocessing.Lock提供了一个跨进程的"互斥". http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

编辑回复编辑过的问题:

在你的概念证明中,每个过程都在构建一个Lock().所以你有两个单独的锁.这就是为什么这两个进程都没有等待 您需要在进程之间共享相同的锁.我在multiprocessing文档中链接的部分解释了如何执行此操作.

  • 您链接的部分似乎显示主进程如何生成10个进程,将Lock对象传递给它创建的每个进程.我的用例不同,因为没有主进程生成子进程.就我而言,每个进程都是完全独立调用的,但它们仍然必须协调. (22认同)
  • 如果对等体之间没有关系,但是他们仍然需要共享的互斥体,则具有配置的数字地址的共享内存可能是唯一的选择。然后,互斥对象可以位于共享内存段中。可能没有针对此的Python API;如果不是这样,您可能必须要本地化。还要确认PThreads完全支持该用例。我担心可能不会。另外,对我来说,这是一种设计气味。似乎您应该使用线程和互斥锁,或者使用诸如redis或riak的单独进程进行仲裁。 (2认同)

Sym*_*mon 9

试试ilock库:

from ilock import ILock

with ILock('Unique lock name'):
    # The code should be run as a system-wide single instance
    ...
Run Code Online (Sandbox Code Playgroud)

  • 如果文件被删除,可能会引发意外异常 (2认同)

Kee*_*ely 9

我的答案与其他答案重叠,但只是为了添加一些人们可以复制粘贴的内容,我经常做这样的事情。

class Locker:
    def __enter__ (self):
        self.fp = open("./lockfile.lck")
        fcntl.flock(self.fp.fileno(), fcntl.LOCK_EX)

    def __exit__ (self, _type, value, tb):
        fcntl.flock(self.fp.fileno(), fcntl.LOCK_UN)
        self.fp.close()
Run Code Online (Sandbox Code Playgroud)

然后将其用作:

print("waiting for lock")
with Locker():
    print("obtained lock")
    time.sleep(5.0)
Run Code Online (Sandbox Code Playgroud)

要进行测试,请touch lockfile.lck在两个或多个不同的终端(来自同一目录)中运行上述代码。

  • 我倾向于希望首先创建文件,通常由超级用户创建,这样单个工作人员就无法删除它。我还想避免在任何工作人员开始之前具有更大权限的东西进入并写入文件,从而可能拒绝他们的访问。我认为创建该文件的工作一直到我的“安装程序”(因为需要一个更好的词),我的偏好是在安装时查看该文件创建的任何问题,而不是在难以调试的运行时查看该文件创建的任何问题。但如果它适合您的应用,那就去做吧! (3认同)
  • @Mattkwish 谢谢,但我建议你不要这样做。任何锁之外的删除都可以随时发生,如果在打开后立即发生,则该文件将从公共文件系统中删除,但带有与私有文件句柄关联的锁。因此,您将有两个单独的文件在运行,并且它不再是全局的。 (2认同)

c z*_*c z 6

只是为了在列表中添加一个,有posix_ipc库,它有一个Semaphore类。

计数为 1 的信号可以用作互斥体。为了完成线程三重奏,SystemEvent库还使用posix_ipc并提供了事件

我还要注意,这也不会轮询您的硬盘驱动器!