【问题标题】:Why .net Threadpool is used only for short time span tasks?为什么.net Threadpool 仅用于短时间跨度任务?
【发布时间】:2010-09-17 07:29:16
【问题描述】:

我在很多地方都读到过 .net 线程池适用于短时间跨度任务(可能不超过 3 秒)。在所有这些提及中,我没有找到不应该使用它的具体原因。

甚至有人说,如果我们使用长时间的任务会导致糟糕的结果,还会导致死锁。

有人可以用简单的英语解释一下为什么我们不应该将线程池用于长时间跨度的任务吗?

具体来说,我什至想给出一个场景,想知道为什么在这个场景中不应该使用ThreadPool,背后有正当的理由。

场景:我需要处理数千个用户数据。用户的处理数据是从本地数据库中检索的,并使用我需要连接到托管在其他位置的 API 的信息,来自 API 的响应将在处理后存储在本地数据库中。

如果我使用线程限制为 20 的 ThreadPool,是否有人可以解释我在这种情况下的陷​​阱?每个用户的处理时间可能从 3 秒到 1 分钟(或更多)不等。

【问题讨论】:

    标签: c# .net multithreading threadpool


    【解决方案1】:

    线程池的意义在于避免创建线程的时间长于使用线程的时间。通过重用现有线程,我们可以避免这种开销。

    缺点是线程池是共享资源:如果您使用的是线程,其他东西就不能。因此,如果您有 很多 个长时间运行的任务,最终可能会导致线程池不足,甚至可能导致死锁。

    不要忘记,您的应用程序代码可能不是唯一使用线程池的代码......系统代码也经常使用它。

    听起来您可能想要拥有自己的生产者/消费者队列,并由少量线程处理它。或者,如果您可以使用异步 API 与您的其他服务通信,您可能会发现您的计算机上的每一位处理都是短暂的。

    【讨论】:

    • 我对您的陈述“系统代码也经常使用它”感到有些困惑。到现在为止,我的理解是系统中的每个进程都会有一个与之关联的线程池?即每个应用程序都有自己的线程池用于其进程。我错了吗?
    【解决方案2】:

    这与线程池调度程序的工作方式有关。它努力确保它不会释放比 CPU 内核更多的等待线程。这是一个好主意,运行比内核更多的线程是浪费的,因为 Windows 花时间在线程之间切换上下文。延长完成工作所需的总时间。

    一旦一个 TP 线程完成,就允许另一个线程运行。每秒两次,TP 调度程序在运行线程未完成时介入。它无法解释为什么这些线程要花这么多时间来完成他们的工作。半秒是 很多 CPU 周期,大约十亿。因此,它假定线程正在阻塞,等待某种 I/O 完成。像 dbase 查询、磁盘读取、套接字连接尝试等等。

    它允许另一个线程运行。你现在有更多的线程然后你有核心。如果这些原始线程确实是阻塞的,这并不是什么问题,它们不会消耗任何 CPU 周期。

    你可以看到这会导致什么:如果你的线程运行了 3 秒,那么它会造成一些僵局。它延迟但不会阻塞等待运行的其他 TP 线程。如果您的线程需要花费大量时间,因为它不断阻塞,那么您最好创建一个常规线程。如果您真的关心线程不会被 TP 调度程序延迟,那么您也应该使用线程。

    顺便说一句,TP 调度程序在 .NET 4.0 中进行了修改,我所写的内容实际上仅适用于早期版本。基础仍然存在,它只是使用了更智能的调度算法。基于反馈,通过测量吞吐量动态调度。只有当您有 很多 个 TP 线程运行时,这才真正重要。

    【讨论】:

      【解决方案3】:

      两个没有真正涉及的原因:

      1. 线程池用作处理 I/O 回调函数的正常方式,通常应该在关联的 I/O 操作完成后很快发生。一般来说,短任务的时效性比长任务更重要,但是线程池中长时间运行的任务会延迟通知任务的执行,而这些通知任务本可以(并且应该)快速启动、运行和完成。
      2. 如果线程池任务在其他线程池任务运行之前被阻塞,它可能会占用线程池线程,从而延迟或在某些情况下完全阻塞该其他任务(或任何其他任务)的启动。

      一般来说,让线程池线程获取锁(必要时等待)不是问题。如果一个线程池线程需要等待另一个线程池线程释放锁,则后一个线程首先获得锁的事实意味着它已经启动。另一方面,等待例如如果使用 I/O 回调例程来标记数据的到达,则某些从连接到达的数据可能会导致死锁。如果太多的线程池线程正在等待 I/O 回调以发出数据已到达的信号,系统可能会决定推迟回调,直到其中一个线程池线程完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-18
        • 2010-09-05
        • 2011-02-25
        • 2012-04-12
        • 1970-01-01
        相关资源
        最近更新 更多