【问题标题】:C# Parallel Execution Thread LimitC# 并行执行线程限制
【发布时间】:2018-01-19 19:06:21
【问题描述】:

我正在编写一个简单的测试,它只记录并发请求开始的时间,然后休眠一秒钟。

static void TestParallelism()
{
    int expectedThreadCount = 100;
    ThreadPool.SetMaxThreads(Environment.CurrentManagedThreadId, expectedThreadCount);
    var module = new WCFCompositeModule();
    module.Initialize(new Keywords());

    var range = Enumerable.Range(0, expectedThreadCount);
    var startTimes = new ConcurrentBag<DateTime>();

    var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = expectedThreadCount };
    Parallel.ForEach(range, i =>
    {
        startTimes.Add(DateTime.Now);
        Thread.Sleep(1000);
    });

    foreach (var time in startTimes)
    {
        Console.WriteLine(string.Format("{0: HH:mm:ss.fff}", time));
    }

    Console.ReadLine();
}

当我使用 100 个预期线程执行此操作时,我可以看到 12 个不同的不同开始时间,所有时间都相差 1 秒。而不是看到它们都在同一秒开始。

样本

13:59:27.475 13:59:26.473 13:59:25.473 13:59:24.471 13:59:23.470 13:59:22.469

这是因为 sleep 阻塞了线程吗?

【问题讨论】:

  • 在不睡觉的情况下试了会发生什么?
  • 没有睡眠,一切都按预期工作

标签: c# multithreading concurrency


【解决方案1】:

您似乎希望这段代码启动 100 个线程,但是

MaxDegreeOfParallelism = expectedThreadCount 

仅设置最大值,而不是最小值,系统会将其分派给任意数量(最多为 MaxDegreeOfParallelism)的线程。

除非您有一台 100 核机器,否则它不太可能用完 100 个线程,因此它使用 X 线程,然后它们都阻塞 1 秒钟,然后在相同的先前 X 线程上调度下一批。这里 x 是 100/12 = 8.333333,所以如果你看到 12 个不同的时间,它会启动至少 12 个不同的批次,这意味着它一次执行 8 到 9 个线程,如果你有一个具有超线程的 4 核系统或 8核心系统这可能是默认行为。

【讨论】:

  • 所以如果我设置它应该工作的最少线程或者因为睡眠仍然阻塞我应该看到类似的结果?
  • @johnny5 sleep 会阻塞调用线程,所以如果你有 100 个线程,每个线程都会等待 1 秒,但这并不意味着它们无论如何都不能同时启动。但是没有简单的方法来设置最小值,当你使用 TPL 时,你让它决定什么是最好的,如果你想要显式控制,手动创建和管理线程(但除非你有一个非常具体的工作负载,你更有可能表现得更差而不是更好)。
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 2011-12-26
相关资源
最近更新 更多