这不是一个明确的答案,但是应该涵盖我已经设法收集的有关此问题的相关详细信息。
首先,Python的线程实现基于Java的。Java的
Condition.signal()文档内容如下:
一个实现可能(并且通常确实)要求在调用此方法时当前线程持有与此Condition相关联的锁。
现在,问题是为什么特别在Python中 强制执行 此行为。但是首先,我想介绍每种方法的利弊。
关于为什么有人认为握住锁通常是一个更好的主意,我发现了两个主要论点:
从服务员一刻开始
acquire()
(即在释放它之前),wait()
可以确保收到信号通知。如果相应的release()
发生在信令之前,则这将允许序列(其中 P = Producer 和 C = Consumer ),P: release(); C: acquire(); P: notify(); C: wait()
在这种情况下,wait()
与acquire()
相同流的对应将丢失信号。在某些情况下,这无关紧要(甚至可以认为更准确),但是在某些情况下,这是不希望的。这是一个论点。当您
notify()
不在锁中时,这可能会导致调度优先级倒置。也就是说,低优先级的线程最终可能会优先于高优先级的线程。考虑一个生产队列,其中有一个生产者和两个消费者( 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(), LC
acquire()在 HC
唤醒之前是无法做到的。这是发生优先级反转的地方。这是第二个论点。
支持在锁之外进行通知的论点是针对高性能线程,其中线程不必为了进入下一个时间片而再次唤醒而重新进入睡眠状态,这已经在线程中进行了解释。我的问题。
Python的threading
模块
正如我所说,在Python中,您必须在通知时按住锁。具有讽刺意味的是,内部实现不允许底层OS避免优先级倒置,因为它在等待者上强制执行FIFO顺序。当然,服务员的顺序是确定性的这一事实可能会派上用场,但问题仍然是为什么在有人认为区分锁和条件变量会更精确时才强制执行这种事情,原因是一些需要优化并发性和最小阻塞的流,
acquire()本身不应注册先前的等待状态,而应仅注册
wait()自身。
可以说,Python程序员无论如何都不会关心这种程度的性能-尽管仍然不能回答为什么在实现标准库时不应允许几种标准行为的问题。
还有一点要说的是,由于
threading某些原因,模块的开发人员可能特别想要FIFO指令,并发现这在某种程度上是实现它的最佳方法,并且希望以此为
Condition代价来建立它。其他(可能更普遍)的方法。为此,他们值得怀疑的好处,直到他们自己解决。



