来自docs:
threading.RLock() - 返回新的可重入锁定对象的工厂函数。必须由获取它的线程释放重入锁。一旦线程获得了可重入锁,同一个线程可以再次获取它而不会阻塞;线程必须在每次获取它时释放一次。
我不知道为什么我们需要这个?
Rlock
和Lock
之间的区别是什么?
答案 0 :(得分:100)
主要区别在于Lock
只能获得一次。在它被释放之前不能再获得它。 (在它被释放后,它可以被任何线程重新获得)。
另一方面,RLock
可以通过同一个线程多次获取。它需要被释放相同的次数才能被解锁"。
另一个区别是获取的Lock
可以由任何线程释放,而获取的RLock
只能由获取它的线程释放。
这是一个示例,说明为什么RLock
有时有用。假设你有:
def f():
g()
h()
def g():
h()
do_something1()
def h():
do_something2()
我们假设所有f
,g
和h
public (即可以由外部来电者直接调用),并且所有这些都需要同步。
使用Lock
,您可以执行以下操作:
lock = Lock()
def f():
with lock:
_g()
_h()
def g():
with lock:
_g()
def _g():
_h()
do_something1()
def h():
with lock:
_h()
def _h():
do_something2()
基本上,由于f
在获取锁定后无法调用g
,因此需要调用" raw"版本g
(即_g
)。所以你最终得到了一个"同步"版本和"原始"每个功能的版本。
使用RLock
优雅地解决问题:
lock = RLock()
def f():
with lock:
g()
h()
def g():
with lock:
h()
do_something1()
def h():
with lock:
do_something2()
答案 1 :(得分:11)
要扩展shx2的answer,为什么要使用一个vs。的原因可能是以下原因:
常规Lock
(互斥体)通常更快,更安全。
使用RLock
的原因是为了避免死锁,例如由于递归。例如,让我们在递归factorial函数中加一个锁。 (当然是人为的)
from threading import Lock
lock = Lock()
def factorial(n):
assert n > 0
if n == 1:
return 1
with lock:
out = n * factorial(n - 1)
return out
此函数将由于递归调用而导致死锁。但是,如果改用RLock
,则递归调用可以根据需要多次重新输入相同的锁。因此,名称 reentrant (或 recursive )锁。
答案 2 :(得分:0)
RLock称为递归锁。基本上,这是只有持有人才能释放的锁。在Lock中,任何线程都可以释放。