我想知道为什么设置block=false
是有意义的?
from multiprocessing import Process, Lock
lock.acquire(block=False)
如果我不需要阻止,我根本不会使用锁定?
从Python in a Nutshell
:
L.acquire()
When 阻塞 为真,获取锁 L .如果 L 已锁定,调用线程挂起并等待 L 已解锁, 然后锁定 L .即使调用线程是上次锁定的线程 L ,它仍然挂起并等待另一个线程 释放 L .什么时候 阻塞 是假的和 L 已解锁,获取锁 L 并返回 True。什么时候 阻塞 是假的和 L 是 锁定,获取不影响 L ,并返回 False。
以及使用以下简单代码的实际示例:
from multiprocessing import Process, Lock, current_process
def blocking_testing(lock):
if not lock.acquire(False):
print('{} Couldn't get lock'.format(current_process().ident))
else:
print('{} Got lock'.format(current_process().ident))
if __name__ == '__main__':
lock = Lock()
for i in range(3):
procs = []
p = Process(target=blocking_testing, args=(lock,))
procs.append(p)
p.start()
for p in procs:
p.join()
使用上述版本(blocking=False
)输出
12208 无法得到锁
如果我设置blocking=True
(或删除它,因为它默认为True
),主进程将挂起,因为Lock
没有被释放。 最后,如果我设置blocking=True
并在最后添加一个lock.release()
,我的输出将是
12618 有锁
我希望这是一个足够清楚的解释。
multiprocessing.Lock
不用于阻止,它用于保护一个或多个资源免受并发访问。
最简单的示例可能是由多个进程写入的文件。要保证一次只有一个进程在给定文件上写入,请使用Lock
保护它。
在某些情况下,您的逻辑无法阻止。例如,如果逻辑由asyncio
模块等事件循环编排,则阻塞将停止整个执行,直到释放Lock
。
在这种情况下,常见的方法是尝试获取Lock
。如果成功,则继续访问受保护的资源,否则将移至其他例程并稍后再试。
这是有意义的,因为它的参数名称:block
。block=False
提供非阻塞功能来访问受保护的资源。
示例一:
您有一个 GUI 线程和一个后台工作线程。您的 GUI 线程需要修改工作线程生成的一些数据,但您的 GUI 线程无法阻塞,因为它会阻塞整个交互。因此,您可以使用lock.acquire(block=False)
安全地检查数据是否已准备就绪,而不会阻塞。
示例二:
另一个与事件循环相关的例子是asyncio
,它提供了对受保护资源的无阻塞访问。