如何在python中创建跨线程跨进程锁?

如何在python中创建跨线程跨进程锁?,python,Python,国家: 此软件包已弃用。强烈建议使用 使用此代码库,而不是紧固件\uuuu或oslo.concurrency 改用 但是,紧固件显然不是螺纹安全的: () 警告:对于单个进程中多个线程的使用情况没有任何保证 我也找不到使用oslo.concurrency的例子 还有一些建议认为,使用flock可以解决这种情况,但flock手册指出: () flock系统调用在与文件描述符fd关联的文件上应用或删除建议锁。锁是通过指定一个操作参数来应用的,该操作参数是lock_SH或lock_EX中的一个,并可选

国家:

此软件包已弃用。强烈建议使用 使用此代码库,而不是
紧固件
\uuuu或
oslo.concurrency
改用

但是,
紧固件
显然不是螺纹安全的:

()

警告:对于单个进程中多个线程的使用情况没有任何保证

我也找不到使用
oslo.concurrency
的例子

还有一些建议认为,使用
flock
可以解决这种情况,但flock手册指出:

()

flock系统调用在与文件描述符fd关联的文件上应用或删除建议锁。锁是通过指定一个操作参数来应用的,该操作参数是lock_SH或lock_EX中的一个,并可选添加lock_NB。要解锁现有锁定操作,应将其锁定

咨询锁允许协作进程对文件执行一致的操作,但不能保证一致性(即,进程仍然可以在不使用咨询锁的情况下访问文件,这可能导致不一致)

所以

下面是一个python程序,它需要在其上实现
lock
unlock
函数,以防止操作一次在一个进程实例中由多个线程执行

(提示:使用
python test.py 1&python test.py 2&python test.py 3启动)

如何修复此代码以使其正常工作

import sys
import time
import random
import threading

def lock():
  pass  # Something here?

def unlock():
  pass  # Something here?

def action(i):
  lock()
  id = threading.current_thread()
  pid = sys.argv[1]
  print("\n")
  for i in range(5):
    print("--> %s - %s - %s " % (i, id, pid))
  unlock()

class Worker(threading.Thread):
  def run(self):
    for i in range(10):
      action(i)

for _ in range(2):
  Worker().start()
当前不正确的输出如下所示:

--> 0 - <Worker(Thread-2, started 123145310715904)> - 2
--> 3 - <Worker(Thread-1, started 123145306509312)> - 1
--> 0 - <Worker(Thread-2, started 123145310715904)> - 1
--> 1 - <Worker(Thread-2, started 123145310715904)> - 2
--> 2 - <Worker(Thread-2, started 123145310715904)> - 2
--> 1 - <Worker(Thread-2, started 123145310715904)> - 1
--> 4 - <Worker(Thread-1, started 123145306509312)> - 1
-->0--2
--> 3 -  - 1
--> 0 -  - 1
--> 1 -  - 2
--> 2 -  - 2
--> 1 -  - 1
--> 4 -  - 1
应该看起来更像:

--> 0 - <Worker(Thread-2, started 123145310715904)> - 1
--> 1 - <Worker(Thread-2, started 123145310715904)> - 1
--> 2 - <Worker(Thread-2, started 123145310715904)> - 1
--> 3 - <Worker(Thread-2, started 123145310715904)> - 1
--> 4 - <Worker(Thread-2, started 123145310715904)> - 1
--> 0 - <Worker(Thread-2, started 123145310715904)> - 2
etc.
-->0--1
--> 1 -  - 1
--> 2 -  - 1
--> 3 -  - 1
--> 4 -  - 1
--> 0 -  - 2
等

同步相关流程

如果您可以更改体系结构,从同一个父级分支出您的流程,这就足够了。例如,这会使线程连续运行:

lock = multiprocessing.Lock()

def thread_proc(lock):
    with lock:
        for i in xrange(0, 10):
            print "IN THREAD", threading.current_thread()
            time.sleep(1)

threads = [threading.Thread(
    target=functools.partial(thread_proc, lock))
    for i in [1, 2]
]
for thread in threads:
    thread.start()
一个潜在的问题可能是,
多处理.Lock
的文档记录稍微不足。我不能给您一个明确的参考,即
多处理.Lock
对象也适合作为线程锁对象

这就是说:在Windows上,
多处理.Lock
是使用实现的,因此您得到了一个跨进程的线程安全锁。在Unix系统上,您会得到一个具有相同属性的

可移植性也可能是一个问题,因为并非所有*NIX系统都有POSIX信号量(FreeBSD仍然有一个端口选项,可以在不支持POSIX信号量的情况下编译Python)

另请参见和Martijn Pieters的评论和

同步不相关的进程

但是,正如您在问题中所述,您有不相关的流程。在这种情况下,您需要一个命名的信号量,Python不提供现成的(尽管它实际上在幕后使用命名的信号量)


库会为您公开这些内容。似乎在所有相关平台上都能工作。

不幸的是,分叉是不可能的。进程生成是在服务器内部完成的,不可修改。这适用于在另一个应用程序中运行的“用户土地”脚本
posix_ipc
似乎很有希望,我会看看它是否可用,但在这种情况下我们确实必须支持OSX,而且该库上的平台限制似乎相当严重。@Doug我无法测试它,因为这里没有MAC,但如果你能在没有超时的情况下使用简单的锁,posix_ipc应该仍然适合你。但本质上,我会测试它。是的,这似乎可以在我们需要的所有平台上工作。:)