为什么多处理锁获取不起作用?
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])
尝试了第一个答案中的 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])