Linux 上 Python 中的系统范围互斥锁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6931342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
System-wide mutex in Python on Linux
提问by emchristiansen
Is there any easy way to have a system-wide mutex in Python on Linux? By "system-wide", I mean the mutex will be used by a group of Python processes; this is in contrast to a traditional mutex, which is used by a group of threadswithin the same process.
有没有什么简单的方法可以在 Linux 上的 Python 中拥有系统范围的互斥锁?通过“系统范围”,我的意思是互斥锁将被一组 Python进程使用;这与传统的互斥锁形成对比,后者由同一进程内的一组线程使用。
EDIT: I'm not sure Python's multiprocessing
package is what I need. For example, I can execute the following in two different interpreters:
编辑:我不确定 Python 的multiprocessing
包是我需要的。例如,我可以在两个不同的解释器中执行以下操作:
from multiprocessing import Lock
L = Lock()
L.acquire()
When I execute these commands simultaneously in two separate interpreters, I want one of them to hang. Instead, neither hangs; it appears they aren't acquiring the same mutex.
当我在两个单独的解释器中同时执行这些命令时,我希望其中一个挂起。相反,两者都没有挂起;看来他们没有获得相同的互斥锁。
采纳答案by zmccord
The "traditional" Unix answer is to use file locks. You can use lockf(3)
to lock sections of a file so that other processes can't edit it; a very common abuse is to use this as a mutex between processes. The python equivalent is fcntl.lockf.
“传统的”Unix 答案是使用文件锁。您可以使用lockf(3)
来锁定文件的某个部分,以便其他进程无法对其进行编辑;一个非常常见的滥用是将其用作进程之间的互斥锁。python 等效项是fcntl.lockf。
Traditionally you write the PID of the locking process into the lock file, so that deadlocks due to processes dying while holding the lock are identifiable and fixable.
传统上,您将锁定进程的 PID 写入锁定文件,以便由于进程在持有锁定时死亡而导致的死锁是可识别和可修复的。
This gets you what you want, since your lock is in a global namespace (the filesystem) and accessible to all processes. This approach also has the perk that non-Python programs can participate in your locking. The downside is that you need a place for this lock file to live; also, some filesystems don't actually lock correctly, so there's a risk that it will silently fail to achieve exclusion. You win some, you lose some.
这可以满足您的需求,因为您的锁位于全局命名空间(文件系统)中并且所有进程都可以访问。这种方法还有一个好处,即非 Python 程序可以参与您的锁定。缺点是你需要一个地方来存放这个锁文件;此外,某些文件系统实际上并没有正确锁定,因此存在无法实现排除的风险。你赢了一些,你输了一些。
回答by wberry
The POSIX standard specifies inter-process semaphores which can be used for this purpose. http://linux.die.net/man/7/sem_overview
POSIX 标准指定了可用于此目的的进程间信号量。 http://linux.die.net/man/7/sem_overview
The multiprocessing
module in Python is built on this API and others. In particular, multiprocessing.Lock
provides a cross-process "mutex". http://docs.python.org/library/multiprocessing.html#synchronization-between-processes
multiprocessing
Python 中的模块基于此 API 和其他 API 构建。特别是,multiprocessing.Lock
提供了一个跨进程的“互斥锁”。 http://docs.python.org/library/multiprocessing.html#synchronization-between-processes
EDITto respond to edited question:
编辑以回应编辑的问题:
In your proof of concept each process is constructing a Lock()
. So you have two separate locks. That is why neither process waits. You will need to share the same lock between processes. The section I linked to in the multiprocessing
documentation explains how to do that.
在您的概念证明中,每个进程都在构建一个Lock()
. 所以你有两个单独的锁。这就是为什么两个进程都不等待的原因。您将需要在进程之间共享相同的锁。我在multiprocessing
文档中链接的部分解释了如何做到这一点。
回答by Ofer
For a system-wide mutex that enables the synchronization of absolutely separate processes (i.e., to INCLUDE Linux processes that do NOT belong to the same processes tree), simply use fcntl.flock. I suppose that using a memory file under Linux' /run/shm folder may make it perform faster.
对于启用绝对独立进程同步的系统范围互斥锁(即,包含不属于同一进程树的 Linux 进程),只需使用fcntl.flock。我想在 Linux 的 /run/shm 文件夹下使用内存文件可能会使其执行速度更快。
See more here.
回答by Symon
回答by c z
Just to add a one to the list, there's the posix_ipclibrary, which has a Semaphore
class.
只是为了在列表中添加一个,还有posix_ipc库,它有一个Semaphore
类。
A Semaphorewith a count of 1 can be used as a Mutex.
To complete the threading trio, the SystemEventlibrary makes use of posix_ipc
and provides an Eventas well.
甲信号量为1的计数可被用作一个互斥。为了完成线程三重奏,SystemEvent库也使用posix_ipc
并提供了一个Event。
回答by Keeely
My answer overlaps with the other answers, but just to add something people can copy-paste, I often do something like this.
我的答案与其他答案重叠,但只是为了添加一些人们可以复制粘贴的内容,我经常做这样的事情。
class Locker:
def __enter__ (self):
self.fp = open("./lockfile.lck", "rb")
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()
And then use it as:
然后将其用作:
print("waiting for lock")
with Locker():
print("obtained lock")
time.sleep(5.0)
To test, do touch lockfile.lck
then run the above code in two or more different terminals (from the same directory).
要进行测试,请touch lockfile.lck
在两个或多个不同的终端(来自同一目录)中运行上述代码。
回答by Sourcerer
Here is an option based on Keely's answer but with some minor errors fixed, and with a folder where lock file is created customized.
这是一个基于 Keely 答案的选项,但修复了一些小错误,并带有一个自定义创建锁定文件的文件夹。
class Locker:
def __enter__ (self, dir):
self.fp = open(os.path.join(dir, ".lock"), "w")
fcntl.flock(self.fp.fileno(), fcntl.LOCK_EX)
def __exit__ (self):
fcntl.flock(self.fp.fileno(), fcntl.LOCK_UN)
self.fp.close()
Because of w
the lock file is automatically created if necessary, you do not need to create it manually.
由于w
锁文件是在必要时自动创建的,您不需要手动创建它。
The usage is the same:
用法是一样的:
with Locker(dir="/path/to/some/dir"):
# Only the current process can operate in /path/to/some/dir
Hope it will be useful for someone.
希望它对某人有用。