Python多线程锁跨线程释放代码逻辑的两大疑问
关于Python threading.Lock的两个疑问解答
先看你提供的代码:
import threading import time shared = 0 lock = threading.Lock() def funcA(): global shared for i in range(10): time.sleep(1) shared += 10 print(f"Thread A wrote: {shared}") lock.acquire() def funcB(): global shared lock.acquire() for i in range(10): time.sleep(1) shared -= 10 print(f"Thread B wrote: {shared}") lock.release() t1 = threading.Thread(target=funcA) t2 = threading.Thread(target=funcB) t1.start() t2.start() t1.join() t2.join()
疑问1:funcA每次循环获取锁但未释放,为何没有报错?
threading.Lock是不可重入锁,它的规则是:同一线程只能获取锁一次,重复调用acquire()不会抛出异常,而是会让当前线程进入阻塞状态(自己死锁自己)。
在funcA的执行流程里:
- 第一次循环:执行完
print后调用lock.acquire(),成功拿到锁。 - 第二次循环:执行到
lock.acquire()时,因为当前线程已经持有这个锁,而Lock不允许同一线程重复获取,所以funcA会卡在这一步,不再继续执行后续循环,但不会抛出任何错误——你看到的“没报错”其实是线程阻塞了,程序并没有正常完成所有10次循环。
疑问2:funcA始终未释放锁,为何funcB能正常再次获取锁?
这是线程启动顺序导致的随机结果:
- 如果
t2.start()后,funcB先执行了lock.acquire(),成功拿到锁,那么funcB会进入循环,每次循环末尾调用lock.release()释放锁。这时候funcA里的lock.acquire()会一直等待,直到funcB释放锁才能获取。 - 反过来,如果funcA先拿到锁,那么funcB的
lock.acquire()会一直阻塞,永远无法进入循环。
另外要注意:这段代码是错误的锁用法,threading.Lock的设计原则是谁获取谁释放,跨线程释放锁属于未定义行为,虽然Python不会直接报错,但会导致锁状态混乱,完全不符合线程安全的设计初衷。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

