这不是一个明确的答案,但它应该涵盖我已经设法收集有关此问题的相关细节.

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called.

现在,问题是为什么在Python中特别强制执行此行为.但首先我要介绍每种方法的优缺点.

至于为什么有人认为握住锁通常是一个更好的主意,我发现了两个主要论点:

>从服务员获取()锁定的那一刻起,即在等待()释放它之前 – 保证会通知信号.如果相应的release()发生在信令之前,这将允许序列(其中P = Producer和C = Consumer)P:release(); C:acquire(); P:notify(); C:wait(),在这种情况下,对应于同一流的acquire()的wait()将错过信号.有些情况下这无关紧要(甚至可能被认为更准确),但有些情况下这是不可取的.这是一个论点.

>当您在锁外通知()时,这可能会导致调度优先级倒置;也就是说,低优先级线程可能最终优先于高优先级线程.考虑具有一个生产者和两个消费者的工作队列(LC =低优先级消费者和HC =高优先级消费者),其中LC当前正在执行工作项并且HC在wait()中被阻止.

可能会出现以下顺序:

P LC HC

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

execute(item) (in wait())

lock()

wq.push(item)

release()

acquire()

item = wq.pop()

release();

notify()

(wake-up)

while (wq.empty())

wait();

如果notify()发生在release()之前,那么在HC被唤醒之前,LC将无法获得().这是优先级倒置发生的地方.这是第二个论点.

支持在锁之外进行通知的论点是高性能线程,其中线程不需要再次进入休眠状态,只是为了在下一次获取切片时再次唤醒 – 这已经解释了它是如何发生的.我的问题.

Python的线程模块

在Python中,正如我所说,你必须在通知时握住锁.具有讽刺意味的是,内部实现不允许底层操作系统避免优先级倒置,因为它会对服务员执行FIFO命令.当然,服务员的顺序是确定性的这一事实可以派上用场,但问题仍然是为什么强制执行这样的事情,因为可以认为区分锁和条件变量会更加精确.一些需要优化并发和最小阻塞的流,acquire()本身不应该注册先前的等待状态,而只能调用wait()调用本身.

可以说,无论如何,Python程序员并不关心这种程度的性能 – 尽管仍然没有回答为什么在实现标准库时,不应该允许几种标准行为的问题.

还有一点需要说明的是,由于某些原因,线程模块的开发人员可能特别想要一个FIFO命令,并发现这是实现它的最佳方式,并且希望将其作为条件来确定其他(可能更普遍)的方法.为此,他们应该得到怀疑的好处,直到他们自己解释它为止.