【发布时间】:2019-12-02 13:39:24
【问题描述】:
TPL 使用什么反馈来动态调整工作线程的数量?
我之前的理解是,它衡量任务完成率,看看添加或删除线程是否值得。但是,为什么这段代码会不断增加线程数,即使信号量会引入瓶颈?
当然,每秒完成的任务不能超过 20 个,超过 2 个线程不会改善这一点。
var activeThreads = 0;
var semaphore = new SemaphoreSlim(2);
var res = Parallel.For(0, 1_000_000, i =>
{
Interlocked.Increment(ref activeThreads);
semaphore.Wait();
try
{
Thread.Sleep(100);
Console.WriteLine("Threads: " + activeThreads);
}
finally
{
Interlocked.Decrement(ref activeThreads);
semaphore.Release();
}
});
【问题讨论】:
-
@Liam 基本上,通过尝试添加另一个线程并测量任务完成率是否增加。如果它减少,放下一个线程。如果它增加,请尝试另一个。然后再次测量并重复。
-
是的,它不会那样做。这将创建大量线程,但随后会阻塞除其中两个之外的所有线程。如果你只想要两个线程,你应该指定
MaxDegreeOfParallelism。Parallel.For并不像你想象的那么聪明。 -
But then, why does this code keep increasing the number of threads, even though there is a bottleneck introduced by a semaphore?你写的东西很慢(从Parallel的角度来看)。它无法看到为什么它很慢 - 但它知道您希望它并行完成。它不能让它运行得更快,所以它只能做它可以做的事情——在问题上抛出线程。 -
这是一个不同的问题@relatively_random,也是一个常见的混淆点。线程池对于它在一个时间窗口内旋转多少线程是保守的。这就是为什么它不会一次旋转一百万个。撇开这样一个事实不谈,如果它这样做了,它就不会是一个池。 :) 如果您想“加速”线程池的初始加速,请致电 docs.microsoft.com/en-us/dotnet/api/…。
-
我怀疑您的问题是您假设
Parallel具有智能(计算何时要求新的Tasks 等)。据我了解,Parallel比较笨。 线程池 具有智能。Parallel可以请求任意数量,线程池 将控制它一次实际获取 的数量(以及它启动的新线程数量等)等等)。 我之所以提到这一点,是因为您关于为什么其他人错了的论点可能是您不清楚Parallel的职责在哪里结束,而线程池的职责从哪里开始。
标签: c# .net task-parallel-library threadpool