Why is the Thread.Start method blocked when the processor is under high load?

For test purposes, I write a CPU voltage program: it just makes N for loops in threads M. I run this program with a lot of threads, say 200. But in the task manager, I see that the thread counter does not exceed some small value, for example 9, and Thread.Start methods wait for the completion of previous running threads.

This behavior is similar to the behavior of ThreadPool, but I expect that regular System.Threading.Threadshould start anyway, without waiting for reasons.

The code below will reproduce this problem and have a workaround option:

using System;
using System.Diagnostics;
using System.Threading;

namespace HeavyLoad
{
    class Program
    {
        static long s_loopsPerThread;
        static ManualResetEvent s_startFlag;

        static void Main(string[] args)
        {
            long totalLoops = (long)5e10;
            int threadsCount = 200; 

            s_loopsPerThread = totalLoops / threadsCount;

            Thread[] threads = new Thread[threadsCount];

            var watch = Stopwatch.StartNew();
            for (int i = 0; i < threadsCount; i++)
            {
                Thread t = new Thread(IntensiveWork);
                t.IsBackground = true;
                threads[i] = t;
            }
            watch.Stop();
            Console.WriteLine("Creating took {0} ms", watch.ElapsedMilliseconds);

            // *** Comment out s_startFlag creation to change the behavior ***
            // s_startFlag = new ManualResetEvent(false);

            watch = Stopwatch.StartNew();
            foreach (var thread in threads)
            {
                thread.Start();
            }
            watch.Stop();
            Console.WriteLine("Starting took {0} ms", watch.ElapsedMilliseconds);

            if (s_startFlag != null)
                s_startFlag.Set();

            watch = Stopwatch.StartNew();
            foreach (var thread in threads)
            {
                thread.Join();
            }
            watch.Stop();
            Console.WriteLine("Waiting took {0} ms", watch.ElapsedMilliseconds);

            Console.ReadLine();
        }

        private static void IntensiveWork()
        {
            if (s_startFlag != null)
                s_startFlag.WaitOne();

            for (long i = 0; i < s_loopsPerThread; i++)
            {
                // hot point
            }
        }
    }
}

1: s_startFlag, . concurrency ( 9 ) :

Creating took 0 ms
Starting took 4891 ms
Waiting took 63 ms

2: s_startFlag, , . 200 : 200 +:

Creating took 0 ms
Starting took 27 ms
Waiting took 4733 ms

? ?

:

  • : Windows 7 Professional
  • Framework: NET 4.6
  • : Intel Core2 Quad Q9550 @2.83
  • : 8
+4
1

, , .

-: totalLoops 100 , . , , . 1 1-2 !

-: # 0 # 1, # 2, # 3, SetThreadAffinityMask (https://sites.google.com/site/dotburger/threading/setthreadaffinitymask-1).

Stopwatch watch;
using (ProcessorAffinity.BeginAffinity(0))
{
    watch = Stopwatch.StartNew();
    for (int i = 0; i < threadsCount; i++)
    {
        Thread t = new Thread(IntensiveWork);
        t.IsBackground = true;
        threads[i] = t;
    }
    watch.Stop();
    Console.WriteLine("Creating took {0} ms", watch.ElapsedMilliseconds);
}

using (ProcessorAffinity.BeginAffinity(1, 2, 3))
{
    for (long i = 0; i < s_loopsPerThread; i++)
    {
    }
}

​​ ( ) , ~ 10 (totalLoops = 5e10).

Creating took 0 ms
Starting took 2282 ms
Waiting took 3681 ms

, MSDN:

Thread.Start , , , .

https://msdn.microsoft.com/en-us/library/1c9txz50(v=vs.110).aspx

: Thread.Start . - .

+1

Source: https://habr.com/ru/post/1610131/


All Articles