【问题标题】:Mono ThreadPool concurrency issuesMono ThreadPool 并发问题
【发布时间】:2014-02-26 01:41:02
【问题描述】:

我编写了一款使用 ThreadPool 进行多线程处理的软件。

ThreadPool.SetMinThreads(128, 128);
ThreadPool.SetMaxThreads(512, 512);

for (int i = 0; i < 40; i++)
{
    ThreadPool.QueueUserWorkItem(_ =>
    {
        Console.Write("!");
        Thread.Sleep(1000);
        Console.Write(".");
    }, null);
}

在每个线程中,我执行阻塞网络操作(使用 http)。 围绕阻塞网络模型设计的软件,我无法转向非阻塞 1 线程 I/O。

它在 Windows 平台上完美运行,我可以在每个内核上使用 128-512 个线程,没有任何问题,一切正常。 但是当我转向单声道时,我看到了一些非常奇怪的行为。我不能让 mono 在每个 CPU 内核上运行多个线程,我可以得到的最大值 - 每个内核 1 个线程,这与我在 SetMinThreads/SetMaxThreads 中指定的内容无关。

在 Linux 下使用 .NET 4/4.5、MONO 版本 3.2.1 和我以前的系统上的一些旧版本进行了尝试。 顺便说一句,纯线程代码效果很好,例如这给出了预期的结果:

for (int i = 0; i < 20; i++)
{
   var t = new Thread(_ => {
      Console.Write("!");
      Thread.Sleep(1000);
      Console.Write(".");
   });
   t.Start();
}

【问题讨论】:

  • 当然我可以重新发明轮子并编写自己的闪亮线程池,它会表现良好(基于最后的代码 sn-p)但它似乎很错误......这种单声道行为的原因是什么?
  • 你应该使用异步http请求等。这样你就不需要很多线程来处理请求了。
  • 512 个线程?!你知道开销有多大吗?如果你不介意我问,你为什么要使用这么多线程?
  • 让我指出,使用大量线程是合法的。如果你有一个现有的应用程序,如果可以避免的话,你不会重写它。你调高线盘。它是一种提高吞吐量的非常省力的工具。如果这足以实现您的目标,那么您将在一分钟内完成。
  • 也就是说,您正在将线程池自动缩放与 IO 绑定任务一起使用。这不起作用,因为线程池不知道正确的并行度。到目前为止,您的方法很可能不是最理想的。

标签: c# mono threadpool


【解决方案1】:

我们还对单声道进行了很多试验,看起来以下内容有所帮助:

  1. 将环境变量 MONO_THREADS_PER_CPU 设置为更高的值。例如 导出 MONO_THREADS_PER_CPU=300 (linux)。我不确定,但如果没有设置“每个 cpu 更多线程”,您将无法通过 setmin/max 线程调整线程池。
  2. 使用 --server 开关运行单声道,但它从 3.2.3 开始工作。这里解释http://www.mono-project.com/Release_Notes_Mono_3.2 ,但只有在没有足够的线程被触发时,这个标志才可能在启动时有帮助。

我们在 linux 上同时使用 options 和 mono 的速度非常快(与 windows 上的 .net 相当)

【讨论】:

  • 这个选项在哪里设置? (MONO_THREADS_PER_CPU)
  • 不确定你的意思,但它是环境变量,所以你在linux上通过“export”设置,在windows上用“set”设置。您也可以查看源代码(搜索 MONO_THREADS_PER_CPU):github.com/mono/mono/blob/…
  • 这是真正的交易 - Npgsql 的异步 DNS 名称解析有问题,原来这是因为默认情况下单声道上的小线程池。增加到(我知道,太大,仍在调整...)2000 而不是默认的 50,瞧,Npgsql 或我之前遇到的任何其他线程池死锁不再有问题。
  • 我们一直在看到我们认为是跨 SSH、HTTPS 到多个端点和数据库访问的随机超时。这解决了我们关于超时问题的问题。谢谢你,我们真的欠你的。
  • 完成上述操作后,我们还必须在 4 CPU/核 VM 上将 ThreadPool.SetMaxThreads 设置得足够高。当它很低时,我们看到了超时,一旦我们将它向上移动,事情又开始工作了。仅在 4 个 CPU/核心 VM 上。
【解决方案2】:

如果多线程不足以满足您的工作,您为什么不使用这些东西的组合(例如:异步、多线程、并行)!? 我认为这些可能对您有帮助: http://mono-for-android.1047100.n5.nabble.com/Task-Parallel-Framework-issues-td5711359.html stackoverflow.com/questions/5717059/implementation-of-task-in-monodroid http://blog.errorok.com/2012/08/09/268/

【讨论】:

  • 我不针对任何移动平台。我在 Linux 中的 Virtual Box 中尝试了这段代码。不,它不会将我的工作添加到单一线程。它必须使用我使用 SetMinThread/SetMaxThread 提供的最小/最大线程设置,并将额外任务排队以供以后执行。正如我所说的,代码在 windows 下完美运行,但在 mono/linux 下表现不佳。
  • 哦!我没有注意第一行。好的,但是您对结合使用几种技术有什么想法?
  • Parallel.For 也不起作用 - 同样的问题,一切都是单线程的,而在 Windows 上,在一个内核上获得多达 512 个线程是没有问题的。而且我需要控制每个任务的最大线程数,ThreadPool 似乎是我最简单的解决方案,但由于某些奇怪的原因,它在所有版本中都出现在单声道上 %)
  • 你说你在 Linux 上的 Virtual-Box 上测试它。你确定你为你的 Linux 虚拟机设置的 CPU‌ 属性没问题?
  • 没有任何特殊选项。我试过 1 和 4 cpu。如果我设置 4 cpus 我得到 4 个线程,如果我设置 1 我得到 1 个线程...
猜你喜欢
  • 2014-06-17
  • 2011-02-09
  • 1970-01-01
  • 2011-10-15
  • 2013-09-29
  • 2010-09-27
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
相关资源
最近更新 更多