Lock和RLock有啥区别

Posted

技术标签:

【中文标题】Lock和RLock有啥区别【英文标题】:What is the difference between Lock and RLockLock和RLock有什么区别 【发布时间】:2014-05-18 02:57:40 【问题描述】:

来自docs:

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

我不确定我们为什么需要这个? RlockLock 有什么区别?

【问题讨论】:

【参考方案1】:

主要区别在于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,它需要调用g的“原始”版本(即_g)。因此,您最终会得到每个函数的“同步”版本和“原始”版本。

使用RLock 优雅地解决了问题:

lock = RLock()

def f():
  with lock:
    g()
    h()

def g():
  with lock:
    h()
    do_something1()

def h():
  with lock:
    do_something2()

【讨论】:

那么使用Lock 有什么实际的“好处”吗? @MateenUlhaq,是的。 Lock 操作更快。 对不起,如果这是一个愚蠢的问题,但为什么我要多次获取锁,如果我需要增加一个计数器,我只需获取一个 Lock() 并释放它,为什么我们需要一个计数器保持递增或递减 @PirateApp 假设您获得了粒度锁(即:在文件上)并做一些相当昂贵的事情(即:解密它)。 rlock 可以防止在一系列复杂的依赖关系中形成死锁,这些依赖关系也可能会尝试获取相同的锁。 @MateenUlhaq 我很抱歉。我已阅读此评论“@MateenUlhaq,是的。锁定操作更快。- shx2 18 年 11 月 22 日 18:11”并且完全错过了它是由 shx2 而不是你。我的同事曾经使用 Lock(),但我发现 RLock() 看起来更好更安全。所以我确实想知道:为什么有人会使用 Lock()?【参考方案2】:

为了扩展 shx2 的 answer,为什么要使用一个与另一个的原因可能如下:

普通的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)锁。

【讨论】:

认为你想要if n ==1: return 1 你说得对,我更新了逻辑以从非递归分支开始。【参考方案3】:

RLock 称为递归锁。基本上它是一个只有持有者才能释放的锁。在Lock中,任何线程都可以释放。

【讨论】:

en.wikipedia.org/wiki/Reentrant_mutex -> 在计算机科学中,可重入互斥锁(recursive mutex,递归锁)是一种特殊类型的互斥(mutex)设备,可以被同一个进程/线程多次锁定,而不会导致死锁。

以上是关于Lock和RLock有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

yarn.lock 和 npm 的 package-lock 有啥区别?

Ruby on Rails 中的 Gemfile 和 Gemfile.lock 有啥区别

C++中unique_lock和shared_lock有啥区别

yarn.lock 和 npm 的 shrinkwrap 有啥区别?

pthread_join 和 pthread_mutex_lock 有啥区别?

NPM5,package-lock.json 和 package.json 有啥区别?