Lock和RLock有什么区别

时间:2014-04-05 19:34:28

标签: python multithreading locking reentrancy

来自docs

  

threading.RLock() -   返回新的可重入锁定对象的工厂函数。必须由获取它的线程释放重入锁。一旦线程获得了可重入锁,同一个线程可以再次获取它而不会阻塞;线程必须在每次获取它时释放一次。

我不知道为什么我们需要这个? RlockLock之间的区别是什么?

3 个答案:

答案 0 :(得分:100)

主要区别在于Lock只能获得一次。在它被释放之前不能再获得它。 (在它被释放后,它可以被任何线程重新获得)。

另一方面,RLock可以通过同一个线程多次获取。它需要被释放相同的次数才能被解锁"。

另一个区别是获取的Lock可以由任何线程释放,而获取的RLock只能由获取它的线程释放。


这是一个示例,说明为什么RLock有时有用。假设你有:

def f():
  g()
  h()

def g():
  h()
  do_something1()

def h():
  do_something2()

我们假设所有fgh 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中,任何线程都可以释放。