【问题标题】:Putting a thread to sleep until event X occurs让线程休眠直到事件 X 发生
【发布时间】:2010-05-10 02:52:22
【问题描述】:

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

线程A从HandlerFactory类请求并获取foo.txt的文件句柄

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

handler 类识别出这个文件句柄已经被检出

处理程序类使线程 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]

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

【问题讨论】:

    标签: python concurrency multithreading locking


    【解决方案1】:

    您要查找的内容称为条件变量。

    Condition Variables

    Here 是 Python 2 库参考。
    对于 Python 3,可以找到 here

    【讨论】:

      【解决方案2】:

      看起来您想要一个与每个处理程序关联的threading.Semaphore(其他同步对象,如事件和条件也是可能的,但信号量似乎最适合您的需要)。 (具体来说,使用BoundedSemaphore: 对于您的用例,这将立即引发异常,因为编程错误会错误地释放信号机的次数超过获取信号机的次数——这正是 bounded 信号机版本;-)。

      在构建时将每个信号量初始化为1 的值(这意味着处理程序可用)。每个 using-thread 在信号量上调用acquire 以获取处理程序(这可能会阻塞它),并在处理程序完成时调用release(这将完全解除阻塞等待线程之一)。这比 Condition 的获取/等待/通知/发布生命周期更简单,而且更具前瞻性,因为正如 Condition 文档所说:

      当前实现唤醒 正好一个线程,如果有的话 等待。但是,这样做并不安全 依赖这种行为。一个未来, 优化的实现可能 偶尔醒来不止一个 线程。

      在使用信号量时,您可以安全地使用它(可以安全依赖的语义:如果信号量初始化为 N,则始终介于 0 和 N-1 之间 [ [包括]] 已成功获取信号量但尚未释放的线程)。

      【讨论】:

        【解决方案3】:

        您确实意识到 Python 有一个巨大的锁,因此您无法获得多线程的大部分好处,对吧?

        除非主线程出于某种原因需要对每个工作线程的结果进行处理,否则您可能希望考虑为每个请求分叉另一个进程。那时您将不必处理锁定问题。让孩子们做他们需要做的事,然后死去。如果他们确实需要返回通信,请通过管道、使用 XMLRPC 或通过 sqlite 数据库(这是线程安全的)进行。

        【讨论】:

        • GIL 不会显着降低 I/O 性能,只会降低处理性能(请参阅wiki.python.org/moin/GlobalInterpreterLock)。由于 OP 似乎正在使用线程来并行化 I/O,因此您断言他正在失去多线程的大部分好处是没有根据的。
        • 我建议您查看dabeaz.com/python/GIL.pdf 引用的 PDF 文件的第 38 页。即使使用 1 个 CPU,如果您使用多个 python 线程,由于检查 GIL 的开销,GIL 也会降低多核系统(有时是单核系统)上 I/O 绑定线程的响应时间。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-10
        • 2014-04-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多