python线程同步主要用lock和rlock:lock不允许多次加锁,同一线程重复acquire会死锁;rlock支持重入,同一线程可多次acquire/release,适合递归或嵌套场景。

Python线程同步主要靠 Lock(互斥锁)和 RLock(可重入锁)来控制多线程对共享资源的访问。它们都能防止竞态条件,但适用场景不同——关键区别在于“是否允许同一线程多次获取同一把锁”。
Lock:最基础的互斥锁
Lock 是一个简单的二值信号量:只有“已锁定”和“未锁定”两种状态。一旦被某个线程 acquire(),其他线程(包括自己)再调用 acquire() 就会阻塞,直到它被 release()。
- 不支持同一线程重复加锁;第二次 acquire() 会死锁(线程卡住)
- 必须由加锁的线程来释放,且只能 release() 一次(否则报 RuntimeError)
- 适合保护一段简单、不嵌套的临界区
示例:
lock = threading.Lock()lock.acquire()
lock.acquire() # ❌ 这里会永久阻塞
RLock:支持重入的锁
RLock 全称 Reentrant Lock,允许同一线程多次 acquire(),内部维护计数器和持有者标识。只有当该线程调用同样次数的 release() 后,锁才真正释放,其他线程才能获取。
立即学习“Python免费学习笔记(深入)”;
- 同一线程可多次 acquire(),不会死锁
- release() 必须由同一线程调用,且次数要匹配;少调用会留锁,多调用会报错
- 适合递归调用、函数嵌套等需要多次进入临界区的场景
示例:
rlock = threading.RLock()rlock.acquire()
rlock.acquire() # ✅ 正常通过
rlock.release()
rlock.release() # ✅ 完全释放
怎么选?看使用模式
- 如果只是在单个函数里保护一段数据(比如更新一个全局计数器),用 Lock 更轻量、语义清晰
- 如果涉及递归、封装了加锁逻辑的工具函数、或多个方法都可能操作同一资源(且可能被同一个线程反复调用),选 RLock
- 注意:RLock 比 Lock 开销稍大,不要无脑替换;也不是万能的——它不能解决线程间协作问题(如生产者-消费者),这时需配合 Condition 或 Queue
实用建议
- 优先用 with 语句自动管理锁(避免忘记 release):
with lock:
# 临界区代码 - 避免锁嵌套过深;尽量减小临界区范围,提升并发性能
- 调试时留意死锁迹象:程序卡住、CPU 占用低、多个线程都在 wait 状态
- 复杂同步逻辑建议用 queue.Queue(线程安全)或 threading.Condition,而非手动拼锁










