Python threading库中acquire和release的工作机制我是否理解正确?
结论
你的理解完全正确,threading.Lock()作为互斥锁的核心运行逻辑和你说的一致,不过有几个容易踩坑的细节需要注意。
核心逻辑验证
你代码里使用的是Python标准库的互斥锁(Mutex),只要所有线程申请的是同一个threadLock实例:
- 当任意一个线程执行
threadLock.acquire()成功拿到锁之后,其他所有调用threadLock.acquire()的线程都会进入阻塞等待状态 - 只有持有锁的线程执行完
threadLock.release()释放锁之后,才会有一个等待的线程拿到锁进入临界区执行 - 因此
acquire()和release()包裹的代码段(临界区),同一时间最多只有一个线程在执行,完全符合你的理解。
注意事项
- 锁的互斥特性只针对同一个锁实例生效:如果你不同线程操作的是不同的
Lock()实例,互相之间不会有约束,临界区的线程安全也无法保证。你当前代码里的threadLock是全局共用的同一个实例,没有问题。 - 手动写
release()容易出现漏释放的问题:如果临界区(print_date函数)执行过程中抛出异常没有被捕获,release()就不会执行,其他所有等待锁的线程会永远阻塞。更稳妥的写法是用with上下文管理器操作锁,不需要手动调用release(),哪怕代码抛出异常也会自动释放锁,示例如下:
def run(self): print("Starting" + self.name) with threadLock: print_date(self.name, self.counter) print("Exiting" + self.name)
Lock是不可重入锁:同一个线程如果已经持有锁的情况下再次调用acquire(),会直接发生死锁,不要在临界区内部再次申请同一个Lock实例。如果有同线程内多次加锁的需求,可以换成threading.RLock()可重入锁。
内容的提问来源于stack exchange,提问作者user15747606
相关产品推荐
相关产品推荐

