死锁是多线程竞争资源时因循环等待导致程序卡住的现象,如线程A持lock1等lock2、B持lock2等lock1;避免方法是统一加锁顺序并使用RLock支持同线程重复加锁,防止自我阻塞。

在Python多线程编程中,死锁(Deadlock)是一个常见且棘手的问题。它通常发生在多个线程竞争多个锁资源时,彼此相互等待对方释放锁,导致所有线程都无法继续执行。
什么是死锁?
假设有两个线程 A 和 B,以及两把锁 lock1 和 lock2:
- 线程 A 持有 lock1,并试图获取 lock2
- 线程 B 持有 lock2,并试图获取 lock1
这时,A 等 B 释放 lock2,B 等 A 释放 lock1,形成循环等待,程序卡住——这就是典型的死锁。
示例:产生死锁的代码
立即学习“Python免费学习笔记(深入)”;
import threading import timelock1 = threading.Lock() lock2 = threading.Lock()
def thread_1(): with lock1: print("线程1 获取了 lock1") time.sleep(1) print("线程1 尝试获取 lock2") with lock2: print("线程1 获取了 lock2")
def thread_2(): with lock2: print("线程2 获取了 lock2") time.sleep(1) print("线程2 尝试获取 lock1") with lock1: print("线程2 获取了 lock1")
t1 = threading.Thread(target=thread_1) t2 = threading.Thread(target=thread_2)
t1.start() t2.start()
t1.join() t2.join()
运行这段代码,大概率会卡住,出现死锁。
如何避免死锁?使用递归锁 RLock
虽然 RLock(可重入锁)不能直接解决多锁交叉导致的死锁,但它允许同一个线程多次获取同一把锁,防止因重复加锁导致的自我阻塞。
更重要的是,避免死锁的关键是:保持加锁顺序一致。
改进方案:统一加锁顺序 + 使用 RLock 防止重复加锁问题
import threading import time使用 RLock 替代 Lock,支持同一线程重复进入
lock1 = threading.RLock() lock2 = threading.RLock()
def worker_1(): print("线程1 开始") with lock1: print("线程1 获取 lock1") time.sleep(0.5) with lock2: # 统一先 lock1 再 lock2 print("线程1 获取 lock2")
def worker_2(): print("线程2 开始") with lock1: # 同样先获取 lock1 print("线程2 获取 lock1") time.sleep(0.5) with lock2: print("线程2 获取 lock2")
t1 = threading.Thread(target=worker_1) t2 = threading.Thread(target=worker_2)
t1.start() t2.start()
t1.join() t2.join()
这个版本中,两个线程都按照 lock1 → lock2 的顺序加锁,避免了循环等待,从而防止死锁。
递归锁 RLock 的典型用途
当一个函数在持有锁的情况下调用另一个也需要同一把锁的函数时,普通 Lock 会导致阻塞,而 RLock 允许这种情况。
import threadingrlock = threading.RLock()
def func1(): with rlock: print("func1 已加锁") func2() # 调用另一个需要同样锁的函数
def func2(): with rlock: # 同一线程可再次获取锁 print("func2 也获得了锁")
t = threading.Thread(target=func1) t.start() t.join()
如果这里用的是 Lock(),程序会在进入 func2 时被自己阻塞。
总结建议
- 死锁主因是锁的获取顺序不一致或循环等待
- 使用 threading.RLock 可解决同一线程重复加锁问题
- 避免死锁的根本方法是:始终以相同顺序获取多个锁
- 设计时尽量减少锁的数量和嵌套层级
- 可以使用超时机制(
acquire(timeout=))来检测潜在死锁
基本上就这些。掌握锁的使用顺序和选择合适的锁类型,能有效避免多线程中的死锁问题。











