为什么线程甚至在抢占式多任务操作系统上挨饿(Windows 7)

ssh*_*ssh 10 delphi winapi multithreading delphi-7 multitasking

我写了一个Win32应用程序(在Delphi-7中使用TThread类是32位)来创建100个线程.恢复时的每个线程将连续(在循环中)递增与线程对象相关联的64位计数器(因此不会锁定或共享数据).

如果让系统运行10到15秒并在此之后停止,则应该在每个线程中看到大致相同的计数.但我观察到的是,81个线程在4亿个循环下运行,其余循环超过9.5亿次.与最快的2111万相比,最慢的线程只有2.3亿.

根据MSDN,抢占式多任务处于线程级别(而不是进程级别),因此我的每个线程都应该以循环方式获得其时间片.我在这里错过了什么,为什么会出现这种差异?

编辑1:机器配置:启用超线程的Intel i7 Quad Core 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;
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 10

循环调度是内核的明显策略.然而,这不是Windows调度程序的工作方式.过去,在Windows 9x时代,它曾经是一个能够为各种虚拟机提供相同时间的调度程序.但是在Dave Cutler的小组开始的NT分支中,调度完全基于优先级.

无论什么线程具有最高优先级获得cpu.Windows中还有另一块代码,它们具有线程优先级,并根据线程创建时的默认优先级进行修改.该代码知道像拥有一个位于前台的窗口的线程之类的东西.或者正在等待已发出信号的同步对象的线程.或者是试图解决优先级倒置问题的更奇怪的调度问题.随机给一个线程一个机会运行,即使它不是轮到它.

专注于首先编写理智的代码.开始一百个线程并不是一件非常理智的事情.您正在尝试消耗机器实际上没有的资源,没有人拥有一百个内核的机器.然而.两个人的权力,首先得到一个128核心的机器.

  • 此外,就像汉斯所说,等待I/O或彼此的1000个线程是正常的,100个就绪/正在运行的线程最多浪费堆栈空间,如果线程频繁访问[(L1缓存大小/ threadsCount)或更多]大量的数据(是的,不是OP代码中的情况),然后大量的CPU /内存带宽可能会浪费在缓存交换上. (3认同)
  • 这里有好的圣人话.也就是说,两位的力量并不完全正确.AMD一直在推出时髦的6核,12核和24核机器. (3认同)