将线程置于睡眠状态直到事件X发生

时间:2010-05-10 02:52:23

标签: python concurrency multithreading locking

我正在写一个线程应用程序中的许多文件,我正在为每个文件创建一个处理程序。我有HandlerFactory类来管理这些处理程序的分发。我想做的是

线程A从HandlerFactory类

请求并获取foo.txt的文件句柄

线程B请求foo.txt的文件处理程序

处理程序类识别出已检出此文件句柄

处理程序类将线程A置于休眠状态

线程B使用HandlerFactory

中的包装器方法关闭文件句柄

HandlerFactory通知休眠线程

线程B唤醒并成功获取foo.txt的文件句柄

这是我到目前为止所拥有的,

def get_handler(self, file_path, type):
    self.lock.acquire()
    if file_path not in self.handlers:
        self.handlers[file_path] = open(file_path, type)
    elif not self.handlers[file_path].closed:
        time.sleep(1)
    self.lock.release()
    return self.handlers[file_path][type]

我相信这成功地涵盖了睡眠和处理程序检索,但我不确定如何唤醒所有线程,甚至更好地唤醒特定线程。

3 个答案:

答案 0 :(得分:6)

您正在寻找的是一个条件变量。

Condition Variables

Here是Python 2库引用 对于Python 3,可以找到here

答案 1 :(得分:2)

看起来你想要一个threading.Semaphore与每个处理程序相关联(其他同步对象,如事件和条件也是可能的,但信号量似乎最简单,满足您的需求)。 (具体来说,使用BoundedSemaphore:对于您的用例,会立即引发异常,因为编程错误会错误地释放semaphone的次数超过获取它的次数 - 而这正是成为的原因有限的版本的semaphones; - )。

在构建它时将每个信号量初始化为值1(这意味着处理程序可用)。每个使用线程调用信号量上的acquire来获取处理程序(可以阻止它),并且当它使用处理程序完成时会release(它将解锁其中一个等待线程)。这比条件的获取/等待/通知/发布生命周期更简单,并且更具未来性,因为条件的文档说:

  

目前的实施已经醒来   正好一个线程,如果有的话   等候。但是,它并不安全   依靠这种行为。未来,   优化实施可能   偶尔醒来不止一个   线程。

使用信号量时,你正在安全地播放( >依赖的语义:如果信号量被初始化为N,则总是在0和N-1之间[ [included]已成功获取信号量且尚未发布信号的线程。)

答案 2 :(得分:0)

你确实意识到Python有一个巨大的锁定,所以多线程的大多数好处都没有得到,对吗?

除非主线程有某些理由对每个工作者的结果做一些事情,否则您可能希望考虑为每个请求分离另一个进程。您不必处理锁定问题。让孩子做他们需要做的事,然后死。如果他们确实需要回传,可以通过管道,使用XMLRPC或通过sqlite数据库(这是线程安全的)进行通信。