rlock允许同一线程多次acquire,lock不行;rlock记录线程id和计数,仅同线程可release,适用递归调用等场景,lock更轻量高效。

RLock 允许同一线程多次 acquire,Lock 不行
这是最直接的行为差异:用 Lock 时,如果同一个线程连续调用两次 acquire(),第二次就会被阻塞(或抛出异常,取决于是否设了 timeout);而 RLock 会记录持有者线程和嵌套次数,同一线程可反复 acquire(),只要 release() 次数匹配即可。
常见错误现象:RuntimeError: release unlocked lock 或线程死锁——往往是因为误把 RLock 当成普通锁用了,却没注意它只认“自己人”(即创建它的线程),其他线程调用 release() 会直接报错。
- 适用场景:递归函数、封装了加锁逻辑的工具方法(比如一个类方法内部调用了另一个也需加锁的方法)
-
Lock更轻量,无状态,适合简单互斥;RLock多了线程 ID 判断和计数开销,性能略低但语义更安全 - 注意:
RLock的release()必须由同一线程调用,且不能多于acquire()次数,否则抛RuntimeError: cannot release un-acquired lock
初始化和使用方式几乎一样,但不能混用
两者都通过 threading.Lock() 和 threading.RLock() 创建,API 表面一致:都有 acquire()、release()、locked() 方法。但它们的实例不兼容——拿 RLock 实例去替换 Lock 变量,代码可能跑通,但语义已变;反之,用 Lock 替换 RLock 很可能在递归调用时崩溃。
常见错误现象:单元测试通过,但高并发下偶发死锁或 RuntimeError——根源常是锁类型被悄悄替换了,或共享了本该隔离的锁实例。
立即学习“Python免费学习笔记(深入)”;
NITC效益型企业网站系统(PHP)产品特色1、企业网站模块:1)网站设计精美:前台页面全部采用DIV+CSS,设计严谨,布局合理,页面精美大气。2)管理操作方便:后台管理界面友好,简单易用,区别于一般CMS系统的复杂与繁琐,功能强大,系统安全,性能稳定。用户使用全自动化控制,功能模块可扩展性强。2、搜索引擎优化: 经众多网络营销专家制定,系统自带搜索引擎基础优化功能,能在最短的时间内提升网站的曝
- 不要用
isinstance(lock, threading.Lock)去判断是否可重入;应该明确声明意图,比如变量名带_rlock后缀 - 配置项上无区别,都不支持超时以外的参数(
timeout是共有的) - 在 context manager(
with语句)中行为一致,但RLock的__exit__仍只做一次release(),对应最近一次acquire()
多线程间共享 RLock 依然需要小心所有权
RLock 的“可重入”只对**单个线程**有效,不是“多线程可重入”。多个线程竞争同一个 RLock 实例时,仍是互斥的——只是获得锁的线程能自己再进,别的线程得等它完全 release() 到计数为 0 才有机会。
容易踩的坑:以为用了 RLock 就能避免死锁,结果因为线程 A 持有锁后调用线程 B 的方法(B 也尝试 acquire 同一把锁),造成跨线程等待链。
- 调试时看
lock._is_owned()(私有属性,仅用于诊断)可确认当前线程是否已持锁 - 不要在回调、信号处理或异步任务中隐式传递
RLock实例,线程上下文很可能已变 - 和
Lock一样,避免锁嵌套顺序不一致(如线程1先锁A再锁B,线程2先锁B再锁A),RLock不解决这个问题
什么时候该选 RLock 而不是 Lock
只有一种情况必须用 RLock:你明确需要**同一执行流内多次进入临界区**,且无法重构为单次加锁。其余情况,优先用 Lock——更简单、更不容易出错、性能略好。
典型误用:给每个实例配一个 RLock 却从不递归调用;或者用 RLock 保护纯读操作(完全没必要)。
- 递归调用场景示例:
def calculate(self): self._lock.acquire(); try: return self._do_calc() finally: self._lock.release(),而_do_calc()内部又调了一次calculate() - 若逻辑可扁平化(比如把锁提到最外层),就别用
RLock;Python 的函数调用栈本身不强制要求锁重入 - 第三方库(如
queue.Queue)内部用的是RLock,但你调用它时完全感知不到——这种封装才是RLock的合理存在理由
真正难的不是选哪个类,而是想清楚“谁在什么时候要进哪段代码”,以及“这段代码会不会被自己再调一次”。锁类型只是表达意图的工具,写错逻辑,换啥锁都救不了。









