为什么线程池以这种方式管理线程?

时间:2022-04-04 21:01:00

Joe Albahari provides a great explanation of the .NET Thread Pool's automatic thread management, and why it works the way it does, in his Threading in C# e-book.

Joe Albahari在他的C#电子书中的线程中提供了.NET Thread Pool的自动线程管理的一个很好的解释,以及它的工作原理。

From what I understand, by default, after occupying all of a processor's cores, the thread pool delays the creation of new threads, because if all processor cores are busy doing computations, creating new threads can no longer improve the overall throughput (tasks completed per second) of the application, and new threads are just a waste of system resources.

根据我的理解,默认情况下,在占用所有处理器核心后,线程池会延迟新线程的创建,因为如果所有处理器核心都在忙于进行计算,那么创建新线程就不能再提高整体吞吐量(每个任务完成的任务)第二)应用程序,新线程只是浪费系统资源。

However, if a task sits in the thread pool queue for too long, the thread pool assumes that a pooled thread is idling or blocked in some way, and tries to take advantage of the downtime by running the task concurrently.

但是,如果任务在线程池队列中停留的时间过长,则线程池会假定池化线程以某种方式空闲或阻塞,并尝试通过同时运行任务来利用停机时间。

Rather than this "delay" algorithm, wouldn't it make more sense, in many situations, to employ a technique whereby thread pool threads have a special property that signals a "waiting" state? It might look something like this:

在许多情况下,使用一种技术可以使线程池线程具有表示“等待”状态的特殊属性,而不是这种“延迟”算法。它可能看起来像这样:

System.Threading.Thread.CurrentThread.IsWaiting = true;

The thread pool would create new threads instantly for queued tasks until all processor cores are occupied with non-waiting threads. Then, tasks are held in the queue until a thread either finishes, OR signals a waiting state.

线程池将立即为排队任务创建新线程,直到所有处理器核心都被非等待线程占用。然后,任务保留在队列中,直到线程结束,或发出等待状态信号。

This would have a couple benefits. First, if a processor core is idle, tasks are always started the instant they are queued to the pool, with no delay. Second, in an application that runs a lot of computationally-intensive tasks that take more than half a second to complete, the thread pool won't continue to burden the system with unnecessary extra threads.

这会有几个好处。首先,如果处理器核心处于空闲状态,则任务总是在它们排队到池中的那一刻开始,没有延迟。其次,在运行大量计算密集型任务的应用程序中,完成所需的时间超过半秒,线程池不会继续给系统带来不必要的额外线程负担。

Of course, there may be some situations in which an application needs to finish tasks within a strict deadline, and can't wait for other tasks to finish first. This algorithm may not work for those applications. Otherwise, I imagine that it will only improve efficiency of multithreaded applications.

当然,在某些情况下,应用程序需要在严格的期限内完成任务,并且不能等待其他任务先完成。此算法可能不适用于那些应用程序。否则,我认为它只会提高多线程应用程序的效率。

What do you think?

你怎么看?

1 个解决方案

#1


0  

We have this information available in the Thread.ThreadState property. But it would not be a good idea for a thread pool to use this information. To use it, we would need communication between threads (the ones in the thread pool, and another gathering the information). That would mean some needs of synchronization, or at least volatile access. Both is really expensive. Thus, we would give a runtime burden to all applications of the ThreadPool, whereas only a few would benefit.

我们在Thread.ThreadState属性中提供了此信息。但是线程池使用这些信息不是一个好主意。要使用它,我们需要线程之间的通信(线程池中的那些,以及收集信息的另一个)。这意味着需要同步,或至少是易失性访问。两者都很贵。因此,我们会给ThreadPool的所有应用程序带来运行时负担,而只有少数会受益。

As a programmer, you have to reflect how your thread pool is used. If the standard behavior is not suitable for you, you can tweak the pool. E.g. using ThreadPool.SetMinThreads, if you know you have a lot of waiting threads. It would not be as automatic as you wish. But your automatization would also not be perfect, since we could have easily too many threads running, when some of the waiting threads wake up simultaneously.

作为程序员,您必须反映线程池的使用方式。如果标准行为不适合您,您可以调整池。例如。使用ThreadPool.SetMinThreads,如果你知道你有很多等待线程。它不会像你想的那样自动化。但是你的自动化也不是很完美,因为当一些等待线程同时唤醒时,我们可以轻松地运行太多线程。

Note, that other thread pools do not have the quite clever extension heurisitc at all, which is build into the C# variant. Normally, you have a fixed number of running threads, and you will never have more than this number running.

注意,其他线程池根本没有非常聪明的扩展heurisitc,它构建在C#变体中。通常,您有一定数量的正在运行的线程,并且您将永远不会运行此数字。

#1


0  

We have this information available in the Thread.ThreadState property. But it would not be a good idea for a thread pool to use this information. To use it, we would need communication between threads (the ones in the thread pool, and another gathering the information). That would mean some needs of synchronization, or at least volatile access. Both is really expensive. Thus, we would give a runtime burden to all applications of the ThreadPool, whereas only a few would benefit.

我们在Thread.ThreadState属性中提供了此信息。但是线程池使用这些信息不是一个好主意。要使用它,我们需要线程之间的通信(线程池中的那些,以及收集信息的另一个)。这意味着需要同步,或至少是易失性访问。两者都很贵。因此,我们会给ThreadPool的所有应用程序带来运行时负担,而只有少数会受益。

As a programmer, you have to reflect how your thread pool is used. If the standard behavior is not suitable for you, you can tweak the pool. E.g. using ThreadPool.SetMinThreads, if you know you have a lot of waiting threads. It would not be as automatic as you wish. But your automatization would also not be perfect, since we could have easily too many threads running, when some of the waiting threads wake up simultaneously.

作为程序员,您必须反映线程池的使用方式。如果标准行为不适合您,您可以调整池。例如。使用ThreadPool.SetMinThreads,如果你知道你有很多等待线程。它不会像你想的那样自动化。但是你的自动化也不是很完美,因为当一些等待线程同时唤醒时,我们可以轻松地运行太多线程。

Note, that other thread pools do not have the quite clever extension heurisitc at all, which is build into the C# variant. Normally, you have a fixed number of running threads, and you will never have more than this number running.

注意,其他线程池根本没有非常聪明的扩展heurisitc,它构建在C#变体中。通常,您有一定数量的正在运行的线程,并且您将永远不会运行此数字。