CodeWalk

threading模块:Lock与RLock的区别

作者:孤独的心 · 2026-05-30 12:55

请解释threading.Lockthreading.RLock(可重入锁)的区别。什么是死锁?如何在同一个线程中安全地多次获取同一把锁?RLock的底层实现原理(acquire计数+所有者线程)是什么?给出一个避免死锁的实际编码示例。

回答

孤独的心

Lock(互斥锁):最基本的锁,同一线程连续两次acquire()会导致死锁。

RLock(可重入锁):允许同一线程多次acquire(),通过维护所有者线程递归计数实现。

lock = threading.Lock()
lock.acquire()
lock.acquire()  # 死锁!

rlock = threading.RLock()
rlock.acquire()
rlock.acquire()  # OK,计数为2
rlock.release()  # 计数1
rlock.release()  # 计数0,真正释放

死锁示例

lock1, lock2 = Lock(), Lock()
def thread_a():
    lock1.acquire()
    lock2.acquire()  # 可能死锁

def thread_b():
    lock2.acquire()
    lock1.acquire()  # 与A形成循环等待

避免死锁的最佳实践

  1. 固定锁获取顺序(锁排序锁)
  2. 使用with语句自动释放
  3. acquire(timeout=...)超时机制
  4. 使用contextlib或线程安全数据结构替代手动锁
# 安全写法
with lock:
    # 临界区
    pass