为什么不改变线程池(或任务)线程的优先级?



在web和Stack Overflow中有很多地方不鼓励更改ThreadPool线程或TPL Task的优先级。特别是:

"您无法控制线程池线程的状态和优先级。"
运行时管理线程池。您无法控制线程的调度,也无法更改线程的优先级。"

"你不应该改变公司文化或优先事项,或者……PoolThread的属性。就像你不会给租来的车喷漆或重新装饰一样。"

在几种情况下,创建和管理自己的线程而不是使用线程池线程是合适的:(例如…)您需要线程具有特定的优先级。"

线程池中的每个线程都以默认优先级运行,更改线程优先级的代码不起作用。

然而,这是一件很简单的事情,并且调试器显示的更改似乎是固定的(只要值可以回读)。

Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
所以问题是,这个禁忌的具体原因是什么?

我怀疑:这样做会扰乱池的微妙负载平衡假设。但这并不能解释为什么有些来源说不能更改它。

线程池,尤其是。net 4.0线程池,有很多妙计,是一个相当复杂的系统。再加上任务、任务调度程序、窃取工作以及其他各种各样的事情,现实是你不知道发生了什么。线程池可能会注意到您的任务正在等待I/O,并决定在您的任务上安排一些快速的事情,或者挂起您的线程来运行更高优先级的事情。您的线程可能以某种方式依赖于更高优先级的线程(您可能意识到,也可能没有意识到),并最终导致死锁。您的线程可能以某种异常方式死亡,无法恢复优先级。

如果你有一个长时间运行的任务,你认为你的线程最好有一个较低的优先级,那么线程池可能不适合你。虽然算法在。net 4.0中得到了改进,但它仍然最适合用于短期任务,在这种情况下,创建新线程的成本与任务的长度不成比例。如果您的任务运行时间超过一两秒钟,那么创建一个新线程的成本是微不足道的(尽管管理可能会很烦人)。

我对一个减小大小的线程池做了一些实验,这似乎表明线程的优先级一旦返回到线程池就会重置为正常。这个关于线程的资源似乎证实了这一点。所以即使你这样做,效果似乎也非常有限。

降低优先级还可能导致意想不到的后果。

想象您在一个应用程序中调度一个任务,但也调用一个库来调度其他几个任务。假设您在应用程序任务运行时降低了线程优先级。如果池中没有产生很多线程,那么在库中可能会有正常优先级的任务等待低优先级的任务完成,但是如果系统的其余部分有许多正常优先级的线程想要运行,那么低优先级的线程可能不会得到太多的CPU时间。

增加池线程的数量可以缓解这个问题,但代价是在堆栈上浪费更多内存,并在上下文切换上花费更多CPU时间。

您当然可以更改它,如果您真的想要,但是考虑到线程池线程被重用,下一个运行的代码可能不期望更改。

如果您更改了任何内容,请使用try/finally来确保您保留了它。

不建议这样做,特别是当您要提高优先级时,因为这会影响系统的整体性能。

不是提供一个过于复杂的答案,但一般来说,线程优先级是一个复杂的主题。例如,Windows有两个相关的描述符:线程优先级和进程优先级。两者的范围从Idle(最低)到Time critical(最高)。当你启动一个新进程时,它被设置为默认的,中间范围(一个正常的进程优先级和一个正常的线程优先级)。

另外,线程优先级是相对的,这意味着即使在繁忙的系统中将线程的优先级设置为最高,也不能确保它将"实时"运行。DotNET对此没有提供保证,Windows也没有。由此你可以看出为什么最好不要去管线程池,因为99.9%的情况下,它知道得最好:)

尽管如此,如果任务涉及较长的计算,降低线程的优先级是可以的。这不会影响其他进程。

但是,应该只对需要快速反应和执行时间短的任务增加优先级,因为这会对其他进程产生负面影响。

相关内容

  • 没有找到相关文章

最新更新