Lock和RLock有啥区别
Posted
技术标签:
【中文标题】Lock和RLock有啥区别【英文标题】:What is the difference between Lock and RLockLock和RLock有什么区别 【发布时间】:2014-05-18 02:57:40 【问题描述】:来自docs:
threading.RLock() -- 返回一个新的可重入锁对象的工厂函数。重入锁必须由获取它的线程释放。一旦一个线程获得了可重入锁,同一个线程可以再次获得它而不会阻塞;线程每次获得它时都必须释放它一次。
我不确定我们为什么需要这个?
Rlock
和 Lock
有什么区别?
【问题讨论】:
【参考方案1】:主要区别在于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
,它需要调用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 有啥区别?