首页 > 解决方案 > 为什么python要求您在等待条件之前获取锁

问题描述

Python 有一个调用的线程对象Condition,它阻塞一个线程,直到另一个线程调用notifiy()notify_all()在它上面。但是,在调用该wait()方法之前,您必须先调用acquire()以获取内部锁。然后该wait()方法释放锁并等待通知,之后它将继续重新获取锁,您可以运行一些需要线程安全的代码。我的问题是,当您调用该方法时,为什么Condition对象不只是在内部自动获取锁:wait()

Python 线程文档

必须在持有相关锁的情况下调用其他方法。该wait()方法释放锁,然后阻塞,直到另一个线程通过调用notify()or唤醒它notify_all()。一旦唤醒,wait()重新获取锁并返回。也可以指定超时。

所以在这段代码中我获得了锁,等待方法立即释放它,然后在它被通知后它再次获得它,然后我最终释放它。

lock = threading.Lock()
condition = threading.Condition(lock=lock)
...
condition.lock()    # acquire the lock
condition.wait()    #  waiting for another thread to notify me
condition.release() # release the lock

为什么wait()调用不只是等待然后在收到通知后获取锁我不明白为什么我要获取它将释放的锁

标签: pythonmultithreadingpython-internals

解决方案


如果您没有持有锁,那么您正在等待的事情可能会您开始等待之前发生。

假设您有一个用 a collections.deque、 athreading.Lock和 athreading.Condition变量实现的自制消息队列。

线程 A 想从队列中读取一个项目,所以它抓取lock,检查deque,并且没有项目。线程 A 调用condition.wait以等待另一个线程放入某些东西。

线程 B 抓取lock、 调用deque.append和 调用condition.notifycondition.notify由于调用,线程 A 现在计划唤醒。

想象一下,如果线程 A 可以释放lock调用之前的condition.wait. condition.notify在这种情况下,线程 B 可能会在线程 A 开始等待之前附加其项目并调用。线程 A 永远不会醒来。


推荐阅读