我写了一个Win32应用程序(在Delphi-7中,32位使用TThread类)来创建100个线程.每个线程在恢复时将连续(循环)增加与线程对象相关联的64位计数器(因此不会锁定或共享数据).
如果让系统运行10到15秒,然后停止,那么每个线程都应该看到大致相同的计数.但是我所观察到的是,81条线程运行不到4亿次循环,其余的循环次数超过9.5亿次.最慢的线程只有2.3亿,而最快的2111万.
根据MSDN,抢占式多任务处于线程级别(不是进程级),所以我的每个线程都应该以循环方式获得时间片段.我在这里缺少什么,为什么这个差异?
编辑1:机器配置:英特尔i7四核3.4GHz,启用超线程(一次8个活动线程).运行Windows-7 64位专业版(测试应用程序是32位)
Edit2(线程代码):测试应用程序是通过优化开启的,没有任何调试信息.在IDE之外运行测试应用程序.
type TMyThread = class(TThread) protected FCount: Int64; public constructor Create; procedure Execute; override; property Count: Int64 read FCount; end; { TMyThread } constructor TMyThread.Create; begin inherited Create(True); FCount := 0; end; procedure TMyThread.Execute; begin inherited; while not Terminated do begin Inc(FCount); end; end;
解决方法
循环调度是内核的一个明显策略.但这并不是Windows调度程序的工作原理.它曾经在Windows 9x天回来,这个调度程序非常有能力让各种虚拟机等待时间.但不是在NT分行,由Dave Cutler的小组开始,调度完全基于优先级.
无论线程具有最高优先级,都可以使用cpu.在Windows中还有一大堆代码修改了线程的优先级,从线程创建时的默认优先级修改它.该代码知道像拥有前台窗口的线程.还是一个等待发出信号的同步对象的线程.或者更为奇怪的调度问题,试图解决优先级倒置问题.随机给线程有机会运行即使不是轮到它.
专注于写出合理的代码.开始一百个线程不是一件很棒的事情.您正在尝试消耗机器实际上不可用的资源,没有人拥有一个具有一百个内核的机器.然而.二的力量,首先得到128个核心的机器.