【问题标题】:Do you need to have the underlying lock to call notify() on a Condition, Python您是否需要底层锁才能在条件上调用 notify(),Python
【发布时间】:2020-10-19 03:12:48
【问题描述】:
只有在拥有 Condition 对象的底层锁时才可以调用 notify()。在文档中清楚地表明,对于 notify_all() 您需要锁。 notify() 也是这种情况,还是在不持有底层锁的情况下在 Condition 上调用 notify() 是否安全。
无论答案是什么,这是 Python 特有的,还是所有/大多数语言中条件变量语义的真理。
谢谢!
【问题讨论】:
标签:
python
multithreading
notify
condition-variable
【解决方案1】:
来自the docs:
如果调用此方法时调用线程尚未获取锁,则会引发 RuntimeError。
这通常适用于所有语言。这有几个原因。一是条件变量代码通常看起来像:
while not some_predicate:
condition_vaiable.wait()
some_predicate 会告诉您您关心的事情何时发生。但是,如果您在检查some_predicate 是否为真时没有持有锁,那么其他一些线程可能在wait 返回和您检查谓词之间修改了它。此外,您通常会等待条件为真,以便对共享资源执行某些操作。例如,您可能正在等待结果可用的信号,您应该对其进行处理。但是,如果该结果不受互斥锁的保护,则访问它是不安全的。您可能会认为,如果只有 1 个线程被通知该对象已准备好,那么只有 1 个线程会处理它,但这样做存在一些问题:
- 互斥锁通常不仅仅保护资源;它还确保必须将寄存器中保存的内存刷新到 RAM,以便其他线程可能正在运行的其他 CPU 可以看到它(由于 GIL,这对于 Python 来说不是这样的问题,但在其他语言中它非常重要) .
- 编译器和 CPU 可以重新排序指令以提高效率,但互斥锁可确保代码中互斥锁释放之前发生的任何事情在优化代码和 CPU 管道中的互斥锁释放之前实际执行。
-
actually hard 确保只有一个线程由
notify 发出信号,因此可能会唤醒多个线程(至少在某些实现中),因此实际上需要确保互斥锁被持有。