为什么多处理锁获取不起作用?

Why doesn't multiprocessing Lock acquiring work?

尝试了第一个答案中的 2 个代码示例:Python sharing a lock between processes。结果是一样的。

import multiprocessing
import time
from threading import Lock


def target(arg):
    if arg == 1:
        lock.acquire()
        time.sleep(1.1)
        print('hi')
        lock.release()
    elif arg == 2:
        while True:
            print('not locked')
            time.sleep(0.5)


def init(lock_: Lock):
    global lock
    lock = lock_


if __name__ == '__main__':
    lock_ = multiprocessing.Lock()
    with multiprocessing.Pool(initializer=init, initargs=[lock_], processes=2) as pool:
        pool.map(target, [1, 2])

为什么这段代码会打印:

not locked
not locked
not locked
hi
not locked

改为

hi
not locked

好吧,将您的工作进程称为“1”和“2”。他们都开始了。 2 打印“not locked”,休眠半秒,循环再次打印“not locked”。但是要注意2打印的是什么与lock是否锁没有关系。代码 2 中甚至没有执行引用 lock,更不用说在 lock 上同步了。又过了半秒,2第三次醒来打印“not locked”,再次进入休眠

在此期间,1 启动,获取锁,休眠 1.1 秒,然后打印“hi”。然后它释放锁并结束。在 1 开始打印“hi”时,2 已经打印了 3 次“not locked”,并且大约 0.1 秒进入了最近的半秒休眠。

打印“hi”后,2 将继续打印“not locked”,大约每秒两次。

所以代码似乎在执行它被告知要做的事情。

不过,我猜不出您是如何期望先看到“hi”然后看到“not locked”的。这将需要某种计时奇迹,其中 2 在 1 运行 超过 1.1 秒之前根本没有开始执行。不是不可能,但极不可能。

变化

这是获得所需输出的一种方法,尽管我对您的意图进行了很多猜测。

如果您不希望 2 在 1 结束之前开始,那么您必须强制。一种方法是让 2 在开始执行时获取 lock。这还需要保证 lock 在任何 worker 开始之前处于已获取状态

所以在调用map()之前获取它。那么让 1 获取它就没有意义了 - 1 可以立即开始,并在结束时释放它,以便 2 可以继续。

代码几乎没有改动,但为了方便起见,我将把所有代码都粘贴在这里:

import multiprocessing
import time
from threading import Lock

def target(arg):
    if arg == 1:
        time.sleep(1.1)
        print('hi')
        lock.release()
    elif arg == 2:
        lock.acquire()
        print('not locked')
        time.sleep(0.5)

def init(lock_: Lock):
    global lock
    lock = lock_


if __name__ == '__main__':
    lock_ = multiprocessing.Lock()
    lock_.acquire()
    with multiprocessing.Pool(initializer=init, initargs=[lock_], processes=2) as pool:
        pool.map(target, [1, 2])