出于测试目的,我编写CPU压力程序:它只是在M个线程中执行N个for-loops。 我用大量的线程运行这个程序,比如说200. 但是在任务管理器中我看到线程计数器没有超过一些小值,比如说9和一个Thread.Start方法等待完成以前的运行线程。为什么Thread.Start方法在CPU负载过高时被阻塞?
这种行为看起来像一个ThreadPool行为,但我期望定期System.Threading.Thread
必须启动无需等待某种原因。下面
代码将重现这一问题,并有解决方法的选择:
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创作的评论,然后启动线程立即开始高密集的CPU工作。在这种情况下,我有一个小的并发(约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专业版
- 框架:NET 4.6
- CPU:英特尔酷四核Q9550 @ 2.83GHz
- RAM:8千兆
可能你正在寻找一个硬件/操作系统限制?例如,磁盘I/O肯定会有最大通道限制,这会导致一些线程被阻塞...... – code4life
此测试不涉及任何磁盘I/O。这看起来像限制“你有CPU负载95%,所以我不启动任何线程”。但我没有听说过这种限制。为什么会发生? –
问题是,究竟是什么导致CPU负载? CPU正在做一些事情,这就是仪器告诉你的。运行一个分析器在这一点上是非常有意义的。 – code4life